Lines Matching +full:bl +full:- +full:data +full:- +full:offset

16 #include <linux/dma-mapping.h>
35 /* ----------------------------------------------------------------------------
147 * struct sh_mobile_lcdc_overlay - LCDC display overlay
152 * @index: Overlay index (0-3)
156 * @alpha: Global alpha blending value (0-255, for alpha blending mode)
163 * @pan_y_offset: Panning linear offset in bytes (luma component)
220 /* -----------------------------------------------------------------------------
284 return chan->cfg->chan == LCDC_CHAN_SUBLCD; in lcdc_chan_is_sublcd()
288 int reg_nr, unsigned long data) in lcdc_write_chan() argument
290 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]); in lcdc_write_chan()
292 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] + in lcdc_write_chan()
297 int reg_nr, unsigned long data) in lcdc_write_chan_mirror() argument
299 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] + in lcdc_write_chan_mirror()
306 return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]); in lcdc_read_chan()
310 int reg, unsigned long data) in lcdc_write_overlay() argument
312 iowrite32(data, ovl->channel->lcdc->base + reg); in lcdc_write_overlay()
313 iowrite32(data, ovl->channel->lcdc->base + reg + SIDE_B_OFFSET); in lcdc_write_overlay()
317 unsigned long reg_offs, unsigned long data) in lcdc_write() argument
319 iowrite32(data, priv->base + reg_offs); in lcdc_write()
325 return ioread32(priv->base + reg_offs); in lcdc_read()
336 /* -----------------------------------------------------------------------------
342 if (atomic_inc_and_test(&priv->hw_usecnt)) { in sh_mobile_lcdc_clk_on()
343 clk_prepare_enable(priv->dot_clk); in sh_mobile_lcdc_clk_on()
344 pm_runtime_get_sync(priv->dev); in sh_mobile_lcdc_clk_on()
350 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) { in sh_mobile_lcdc_clk_off()
351 pm_runtime_put(priv->dev); in sh_mobile_lcdc_clk_off()
352 clk_disable_unprepare(priv->dot_clk); in sh_mobile_lcdc_clk_off()
365 priv->lddckr = LDDCKR_ICKSEL_BUS; in sh_mobile_lcdc_setup_clocks()
369 priv->lddckr = LDDCKR_ICKSEL_MIPI; in sh_mobile_lcdc_setup_clocks()
373 priv->lddckr = LDDCKR_ICKSEL_HDMI; in sh_mobile_lcdc_setup_clocks()
376 return -EINVAL; in sh_mobile_lcdc_setup_clocks()
382 clk = clk_get(priv->dev, str); in sh_mobile_lcdc_setup_clocks()
384 dev_err(priv->dev, "cannot get dot clock %s\n", str); in sh_mobile_lcdc_setup_clocks()
388 priv->dot_clk = clk; in sh_mobile_lcdc_setup_clocks()
392 /* -----------------------------------------------------------------------------
396 static void lcdc_sys_write_index(void *handle, unsigned long data) in lcdc_sys_write_index() argument
400 lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT); in lcdc_sys_write_index()
401 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); in lcdc_sys_write_index()
402 lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA | in lcdc_sys_write_index()
404 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); in lcdc_sys_write_index()
407 static void lcdc_sys_write_data(void *handle, unsigned long data) in lcdc_sys_write_data() argument
411 lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW); in lcdc_sys_write_data()
412 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); in lcdc_sys_write_data()
413 lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA | in lcdc_sys_write_data()
415 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); in lcdc_sys_write_data()
422 lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR); in lcdc_sys_read_data()
423 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); in lcdc_sys_read_data()
424 lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA | in lcdc_sys_read_data()
427 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); in lcdc_sys_read_data()
429 return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK; in lcdc_sys_read_data()
440 struct sh_mobile_lcdc_chan *ch = info->par; in sh_mobile_lcdc_sginit()
441 unsigned int nr_pages_max = ch->fb_size >> PAGE_SHIFT; in sh_mobile_lcdc_sginit()
445 sg_init_table(ch->sglist, nr_pages_max); in sh_mobile_lcdc_sginit()
448 sg_set_page(&ch->sglist[nr_pages++], pageref->page, PAGE_SIZE, 0); in sh_mobile_lcdc_sginit()
456 struct sh_mobile_lcdc_chan *ch = info->par; in sh_mobile_lcdc_deferred_io()
457 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg; in sh_mobile_lcdc_deferred_io()
460 sh_mobile_lcdc_clk_on(ch->lcdc); in sh_mobile_lcdc_deferred_io()
481 dma_map_sg(ch->lcdc->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); in sh_mobile_lcdc_deferred_io()
482 if (panel->start_transfer) in sh_mobile_lcdc_deferred_io()
483 panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops); in sh_mobile_lcdc_deferred_io()
485 dma_unmap_sg(ch->lcdc->dev, ch->sglist, nr_pages, in sh_mobile_lcdc_deferred_io()
488 if (panel->start_transfer) in sh_mobile_lcdc_deferred_io()
489 panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops); in sh_mobile_lcdc_deferred_io()
496 struct fb_deferred_io *fbdefio = info->fbdefio; in sh_mobile_lcdc_deferred_io_touch()
499 schedule_delayed_work(&info->deferred_work, fbdefio->delay); in sh_mobile_lcdc_deferred_io_touch()
504 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg; in sh_mobile_lcdc_display_on()
506 if (ch->tx_dev) { in sh_mobile_lcdc_display_on()
509 ret = ch->tx_dev->ops->display_on(ch->tx_dev); in sh_mobile_lcdc_display_on()
514 ch->info->state = FBINFO_STATE_SUSPENDED; in sh_mobile_lcdc_display_on()
518 if (panel->display_on) in sh_mobile_lcdc_display_on()
519 panel->display_on(); in sh_mobile_lcdc_display_on()
524 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg; in sh_mobile_lcdc_display_off()
526 if (panel->display_off) in sh_mobile_lcdc_display_off()
527 panel->display_off(); in sh_mobile_lcdc_display_off()
529 if (ch->tx_dev) in sh_mobile_lcdc_display_off()
530 ch->tx_dev->ops->display_off(ch->tx_dev); in sh_mobile_lcdc_display_off()
533 /* -----------------------------------------------------------------------------
608 if (var->grayscale > 1) in sh_mobile_format_fourcc()
609 return var->grayscale; in sh_mobile_format_fourcc()
611 switch (var->bits_per_pixel) { in sh_mobile_format_fourcc()
625 return var->grayscale > 1; in sh_mobile_format_is_fourcc()
628 /* -----------------------------------------------------------------------------
632 static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) in sh_mobile_lcdc_irq() argument
634 struct sh_mobile_lcdc_priv *priv = data; in sh_mobile_lcdc_irq()
648 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { in sh_mobile_lcdc_irq()
649 ch = &priv->ch[k]; in sh_mobile_lcdc_irq()
651 if (!ch->enabled) in sh_mobile_lcdc_irq()
657 ch->frame_end = 1; in sh_mobile_lcdc_irq()
658 wake_up(&ch->frame_end_wait); in sh_mobile_lcdc_irq()
666 complete(&ch->vsync_completion); in sh_mobile_lcdc_irq()
680 ldintr = lcdc_read(ch->lcdc, _LDINTR); in sh_mobile_lcdc_wait_for_vsync()
682 lcdc_write(ch->lcdc, _LDINTR, ldintr); in sh_mobile_lcdc_wait_for_vsync()
684 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion, in sh_mobile_lcdc_wait_for_vsync()
687 return -ETIMEDOUT; in sh_mobile_lcdc_wait_for_vsync()
705 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) in sh_mobile_lcdc_start_stop()
706 if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled) in sh_mobile_lcdc_start_stop()
708 tmp = lcdc_read_chan(&priv->ch[k], LDPMR) in sh_mobile_lcdc_start_stop()
723 const struct fb_var_screeninfo *var = &ch->info->var; in sh_mobile_lcdc_geometry()
724 const struct fb_videomode *mode = &ch->display.mode; in sh_mobile_lcdc_geometry()
728 tmp = ch->ldmt1r_value; in sh_mobile_lcdc_geometry()
729 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL; in sh_mobile_lcdc_geometry()
730 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL; in sh_mobile_lcdc_geometry()
731 tmp |= (ch->cfg->flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0; in sh_mobile_lcdc_geometry()
732 tmp |= (ch->cfg->flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0; in sh_mobile_lcdc_geometry()
733 tmp |= (ch->cfg->flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0; in sh_mobile_lcdc_geometry()
734 tmp |= (ch->cfg->flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0; in sh_mobile_lcdc_geometry()
735 tmp |= (ch->cfg->flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0; in sh_mobile_lcdc_geometry()
739 lcdc_write_chan(ch, LDMT2R, ch->cfg->sys_bus_cfg.ldmt2r); in sh_mobile_lcdc_geometry()
740 lcdc_write_chan(ch, LDMT3R, ch->cfg->sys_bus_cfg.ldmt3r); in sh_mobile_lcdc_geometry()
743 h_total = mode->xres + mode->hsync_len + mode->left_margin in sh_mobile_lcdc_geometry()
744 + mode->right_margin; in sh_mobile_lcdc_geometry()
746 tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */ in sh_mobile_lcdc_geometry()
749 hsync_pos = mode->xres + mode->right_margin; in sh_mobile_lcdc_geometry()
751 tmp |= (mode->hsync_len / 8) << 16; /* HSYNW */ in sh_mobile_lcdc_geometry()
755 tmp = mode->yres + mode->vsync_len + mode->upper_margin in sh_mobile_lcdc_geometry()
756 + mode->lower_margin; /* VTLN */ in sh_mobile_lcdc_geometry()
757 tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */ in sh_mobile_lcdc_geometry()
760 tmp = mode->yres + mode->lower_margin; /* VSYNP */ in sh_mobile_lcdc_geometry()
761 tmp |= mode->vsync_len << 16; /* VSYNW */ in sh_mobile_lcdc_geometry()
765 display_h_total = mode->xres + mode->hsync_len + mode->left_margin in sh_mobile_lcdc_geometry()
766 + mode->right_margin; in sh_mobile_lcdc_geometry()
767 tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16) in sh_mobile_lcdc_geometry()
768 | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7); in sh_mobile_lcdc_geometry()
777 if (!ovl->enabled) { in sh_mobile_lcdc_overlay_setup()
778 lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); in sh_mobile_lcdc_overlay_setup()
779 lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0); in sh_mobile_lcdc_overlay_setup()
780 lcdc_write(ovl->channel->lcdc, LDBCR, in sh_mobile_lcdc_overlay_setup()
781 LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); in sh_mobile_lcdc_overlay_setup()
785 ovl->base_addr_y = ovl->dma_handle; in sh_mobile_lcdc_overlay_setup()
786 ovl->base_addr_c = ovl->dma_handle in sh_mobile_lcdc_overlay_setup()
787 + ovl->xres_virtual * ovl->yres_virtual; in sh_mobile_lcdc_overlay_setup()
789 switch (ovl->mode) { in sh_mobile_lcdc_overlay_setup()
791 format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT); in sh_mobile_lcdc_overlay_setup()
796 | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT); in sh_mobile_lcdc_overlay_setup()
800 switch (ovl->format->fourcc) { in sh_mobile_lcdc_overlay_setup()
819 switch (ovl->format->fourcc) { in sh_mobile_lcdc_overlay_setup()
843 lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); in sh_mobile_lcdc_overlay_setup()
845 lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format); in sh_mobile_lcdc_overlay_setup()
847 lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index), in sh_mobile_lcdc_overlay_setup()
848 (ovl->yres << LDBBSSZR_BVSS_SHIFT) | in sh_mobile_lcdc_overlay_setup()
849 (ovl->xres << LDBBSSZR_BHSS_SHIFT)); in sh_mobile_lcdc_overlay_setup()
850 lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index), in sh_mobile_lcdc_overlay_setup()
851 (ovl->pos_y << LDBBLOCR_CVLC_SHIFT) | in sh_mobile_lcdc_overlay_setup()
852 (ovl->pos_x << LDBBLOCR_CHLC_SHIFT)); in sh_mobile_lcdc_overlay_setup()
853 lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index), in sh_mobile_lcdc_overlay_setup()
854 ovl->pitch << LDBBSMWR_BSMW_SHIFT); in sh_mobile_lcdc_overlay_setup()
856 lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); in sh_mobile_lcdc_overlay_setup()
857 lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); in sh_mobile_lcdc_overlay_setup()
859 lcdc_write(ovl->channel->lcdc, LDBCR, in sh_mobile_lcdc_overlay_setup()
860 LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); in sh_mobile_lcdc_overlay_setup()
864 * __sh_mobile_lcdc_start - Configure and start the LCDC
876 /* Enable LCDC channels. Read data from external memory, avoid using the in __sh_mobile_lcdc_start()
879 lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled); in __sh_mobile_lcdc_start()
886 tmp = priv->lddckr; in __sh_mobile_lcdc_start()
887 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { in __sh_mobile_lcdc_start()
888 ch = &priv->ch[k]; in __sh_mobile_lcdc_start()
889 if (!ch->enabled) in __sh_mobile_lcdc_start()
895 m = ch->cfg->clock_divider; in __sh_mobile_lcdc_start()
903 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); in __sh_mobile_lcdc_start()
915 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { in __sh_mobile_lcdc_start()
916 ch = &priv->ch[k]; in __sh_mobile_lcdc_start()
917 if (!ch->enabled) in __sh_mobile_lcdc_start()
922 tmp = ch->format->lddfr; in __sh_mobile_lcdc_start()
924 if (ch->format->yuv) { in __sh_mobile_lcdc_start()
925 switch (ch->colorspace) { in __sh_mobile_lcdc_start()
936 lcdc_write_chan(ch, LDMLSR, ch->line_size); in __sh_mobile_lcdc_start()
937 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); in __sh_mobile_lcdc_start()
938 if (ch->format->yuv) in __sh_mobile_lcdc_start()
939 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); in __sh_mobile_lcdc_start()
941 /* When using deferred I/O mode, configure the LCDC for one-shot in __sh_mobile_lcdc_start()
945 if (ch->ldmt1r_value & LDMT1R_IFM && in __sh_mobile_lcdc_start()
946 ch->cfg->sys_bus_cfg.deferred_io_msec) { in __sh_mobile_lcdc_start()
955 switch (priv->ch[0].format->fourcc) { in __sh_mobile_lcdc_start()
978 priv->started = 1; in __sh_mobile_lcdc_start()
989 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { in sh_mobile_lcdc_start()
990 if (priv->ch[k].enabled) in sh_mobile_lcdc_start()
998 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { in sh_mobile_lcdc_start()
1001 ch = &priv->ch[k]; in sh_mobile_lcdc_start()
1002 if (!ch->enabled) in sh_mobile_lcdc_start()
1005 panel = &ch->cfg->panel_cfg; in sh_mobile_lcdc_start()
1006 if (panel->setup_sys) { in sh_mobile_lcdc_start()
1007 ret = panel->setup_sys(ch, &sh_mobile_lcdc_sys_bus_ops); in sh_mobile_lcdc_start()
1014 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { in sh_mobile_lcdc_start()
1015 ch = &priv->ch[k]; in sh_mobile_lcdc_start()
1016 if (!ch->enabled) in sh_mobile_lcdc_start()
1019 ch->base_addr_y = ch->dma_handle; in sh_mobile_lcdc_start()
1020 ch->base_addr_c = ch->dma_handle in sh_mobile_lcdc_start()
1021 + ch->xres_virtual * ch->yres_virtual; in sh_mobile_lcdc_start()
1022 ch->line_size = ch->pitch; in sh_mobile_lcdc_start()
1025 for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) { in sh_mobile_lcdc_start()
1026 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k]; in sh_mobile_lcdc_start()
1036 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { in sh_mobile_lcdc_start()
1037 ch = &priv->ch[k]; in sh_mobile_lcdc_start()
1038 if (!ch->enabled) in sh_mobile_lcdc_start()
1041 tmp = ch->cfg->sys_bus_cfg.deferred_io_msec; in sh_mobile_lcdc_start()
1042 if (ch->ldmt1r_value & LDMT1R_IFM && tmp) { in sh_mobile_lcdc_start()
1043 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; in sh_mobile_lcdc_start()
1044 ch->defio.delay = msecs_to_jiffies(tmp); in sh_mobile_lcdc_start()
1045 ch->info->fbdefio = &ch->defio; in sh_mobile_lcdc_start()
1046 fb_deferred_io_init(ch->info); in sh_mobile_lcdc_start()
1051 if (ch->bl) { in sh_mobile_lcdc_start()
1052 ch->bl->props.power = BACKLIGHT_POWER_ON; in sh_mobile_lcdc_start()
1053 backlight_update_status(ch->bl); in sh_mobile_lcdc_start()
1066 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { in sh_mobile_lcdc_stop()
1067 ch = &priv->ch[k]; in sh_mobile_lcdc_stop()
1068 if (!ch->enabled) in sh_mobile_lcdc_stop()
1075 if (ch->info && ch->info->fbdefio) { in sh_mobile_lcdc_stop()
1076 ch->frame_end = 0; in sh_mobile_lcdc_stop()
1077 schedule_delayed_work(&ch->info->deferred_work, 0); in sh_mobile_lcdc_stop()
1078 wait_event(ch->frame_end_wait, ch->frame_end); in sh_mobile_lcdc_stop()
1079 fb_deferred_io_cleanup(ch->info); in sh_mobile_lcdc_stop()
1080 ch->info->fbdefio = NULL; in sh_mobile_lcdc_stop()
1084 if (ch->bl) { in sh_mobile_lcdc_stop()
1085 ch->bl->props.power = BACKLIGHT_POWER_OFF; in sh_mobile_lcdc_stop()
1086 backlight_update_status(ch->bl); in sh_mobile_lcdc_stop()
1093 if (priv->started) { in sh_mobile_lcdc_stop()
1095 priv->started = 0; in sh_mobile_lcdc_stop()
1099 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) in sh_mobile_lcdc_stop()
1100 if (priv->ch[k].enabled) in sh_mobile_lcdc_stop()
1107 if (var->xres > MAX_XRES || var->yres > MAX_YRES) in __sh_mobile_lcdc_check_var()
1108 return -EINVAL; in __sh_mobile_lcdc_check_var()
1113 if (var->xres_virtual < var->xres) in __sh_mobile_lcdc_check_var()
1114 var->xres_virtual = var->xres; in __sh_mobile_lcdc_check_var()
1115 if (var->yres_virtual < var->yres) in __sh_mobile_lcdc_check_var()
1116 var->yres_virtual = var->yres; in __sh_mobile_lcdc_check_var()
1121 format = sh_mobile_format_info(var->grayscale); in __sh_mobile_lcdc_check_var()
1123 return -EINVAL; in __sh_mobile_lcdc_check_var()
1124 var->bits_per_pixel = format->bpp; in __sh_mobile_lcdc_check_var()
1126 /* Default to RGB and JPEG color-spaces for RGB and YUV formats in __sh_mobile_lcdc_check_var()
1129 if (!format->yuv) in __sh_mobile_lcdc_check_var()
1130 var->colorspace = V4L2_COLORSPACE_SRGB; in __sh_mobile_lcdc_check_var()
1131 else if (var->colorspace != V4L2_COLORSPACE_REC709) in __sh_mobile_lcdc_check_var()
1132 var->colorspace = V4L2_COLORSPACE_JPEG; in __sh_mobile_lcdc_check_var()
1134 if (var->bits_per_pixel <= 16) { /* RGB 565 */ in __sh_mobile_lcdc_check_var()
1135 var->bits_per_pixel = 16; in __sh_mobile_lcdc_check_var()
1136 var->red.offset = 11; in __sh_mobile_lcdc_check_var()
1137 var->red.length = 5; in __sh_mobile_lcdc_check_var()
1138 var->green.offset = 5; in __sh_mobile_lcdc_check_var()
1139 var->green.length = 6; in __sh_mobile_lcdc_check_var()
1140 var->blue.offset = 0; in __sh_mobile_lcdc_check_var()
1141 var->blue.length = 5; in __sh_mobile_lcdc_check_var()
1142 var->transp.offset = 0; in __sh_mobile_lcdc_check_var()
1143 var->transp.length = 0; in __sh_mobile_lcdc_check_var()
1144 } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ in __sh_mobile_lcdc_check_var()
1145 var->bits_per_pixel = 24; in __sh_mobile_lcdc_check_var()
1146 var->red.offset = 16; in __sh_mobile_lcdc_check_var()
1147 var->red.length = 8; in __sh_mobile_lcdc_check_var()
1148 var->green.offset = 8; in __sh_mobile_lcdc_check_var()
1149 var->green.length = 8; in __sh_mobile_lcdc_check_var()
1150 var->blue.offset = 0; in __sh_mobile_lcdc_check_var()
1151 var->blue.length = 8; in __sh_mobile_lcdc_check_var()
1152 var->transp.offset = 0; in __sh_mobile_lcdc_check_var()
1153 var->transp.length = 0; in __sh_mobile_lcdc_check_var()
1154 } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ in __sh_mobile_lcdc_check_var()
1155 var->bits_per_pixel = 32; in __sh_mobile_lcdc_check_var()
1156 var->red.offset = 16; in __sh_mobile_lcdc_check_var()
1157 var->red.length = 8; in __sh_mobile_lcdc_check_var()
1158 var->green.offset = 8; in __sh_mobile_lcdc_check_var()
1159 var->green.length = 8; in __sh_mobile_lcdc_check_var()
1160 var->blue.offset = 0; in __sh_mobile_lcdc_check_var()
1161 var->blue.length = 8; in __sh_mobile_lcdc_check_var()
1162 var->transp.offset = 24; in __sh_mobile_lcdc_check_var()
1163 var->transp.length = 8; in __sh_mobile_lcdc_check_var()
1165 return -EINVAL; in __sh_mobile_lcdc_check_var()
1167 var->red.msb_right = 0; in __sh_mobile_lcdc_check_var()
1168 var->green.msb_right = 0; in __sh_mobile_lcdc_check_var()
1169 var->blue.msb_right = 0; in __sh_mobile_lcdc_check_var()
1170 var->transp.msb_right = 0; in __sh_mobile_lcdc_check_var()
1174 if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > in __sh_mobile_lcdc_check_var()
1175 info->fix.smem_len) in __sh_mobile_lcdc_check_var()
1176 return -EINVAL; in __sh_mobile_lcdc_check_var()
1181 /* -----------------------------------------------------------------------------
1182 * Frame buffer operations - Overlays
1189 struct sh_mobile_lcdc_overlay *ovl = info->par; in overlay_alpha_show()
1191 return sysfs_emit(buf, "%u\n", ovl->alpha); in overlay_alpha_show()
1199 struct sh_mobile_lcdc_overlay *ovl = info->par; in overlay_alpha_store()
1207 if (endp - buf != count) in overlay_alpha_store()
1208 return -EINVAL; in overlay_alpha_store()
1211 return -EINVAL; in overlay_alpha_store()
1213 if (ovl->alpha != alpha) { in overlay_alpha_store()
1214 ovl->alpha = alpha; in overlay_alpha_store()
1216 if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled) in overlay_alpha_store()
1227 struct sh_mobile_lcdc_overlay *ovl = info->par; in overlay_mode_show()
1229 return sysfs_emit(buf, "%u\n", ovl->mode); in overlay_mode_show()
1237 struct sh_mobile_lcdc_overlay *ovl = info->par; in overlay_mode_store()
1245 if (endp - buf != count) in overlay_mode_store()
1246 return -EINVAL; in overlay_mode_store()
1249 return -EINVAL; in overlay_mode_store()
1251 if (ovl->mode != mode) { in overlay_mode_store()
1252 ovl->mode = mode; in overlay_mode_store()
1254 if (ovl->enabled) in overlay_mode_store()
1266 struct sh_mobile_lcdc_overlay *ovl = info->par; in overlay_position_show()
1268 return sysfs_emit(buf, "%d,%d\n", ovl->pos_x, ovl->pos_y); in overlay_position_show()
1276 struct sh_mobile_lcdc_overlay *ovl = info->par; in overlay_position_store()
1283 return -EINVAL; in overlay_position_store()
1289 if (endp - buf != count) in overlay_position_store()
1290 return -EINVAL; in overlay_position_store()
1292 if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) { in overlay_position_store()
1293 ovl->pos_x = pos_x; in overlay_position_store()
1294 ovl->pos_y = pos_y; in overlay_position_store()
1296 if (ovl->enabled) in overlay_position_store()
1307 struct sh_mobile_lcdc_overlay *ovl = info->par; in overlay_rop3_show()
1309 return sysfs_emit(buf, "%u\n", ovl->rop3); in overlay_rop3_show()
1317 struct sh_mobile_lcdc_overlay *ovl = info->par; in overlay_rop3_store()
1325 if (endp - buf != count) in overlay_rop3_store()
1326 return -EINVAL; in overlay_rop3_store()
1329 return -EINVAL; in overlay_rop3_store()
1331 if (ovl->rop3 != rop3) { in overlay_rop3_store()
1332 ovl->rop3 = rop3; in overlay_rop3_store()
1334 if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled) in overlay_rop3_store()
1366 struct sh_mobile_lcdc_overlay *ovl = info->par; in sh_mobile_lcdc_overlay_pan()
1372 if (!ovl->format->yuv) { in sh_mobile_lcdc_overlay_pan()
1373 y_offset = (var->yoffset * ovl->xres_virtual + var->xoffset) in sh_mobile_lcdc_overlay_pan()
1374 * ovl->format->bpp / 8; in sh_mobile_lcdc_overlay_pan()
1377 unsigned int xsub = ovl->format->bpp < 24 ? 2 : 1; in sh_mobile_lcdc_overlay_pan()
1378 unsigned int ysub = ovl->format->bpp < 16 ? 2 : 1; in sh_mobile_lcdc_overlay_pan()
1380 y_offset = var->yoffset * ovl->xres_virtual + var->xoffset; in sh_mobile_lcdc_overlay_pan()
1381 c_offset = var->yoffset / ysub * ovl->xres_virtual * 2 / xsub in sh_mobile_lcdc_overlay_pan()
1382 + var->xoffset * 2 / xsub; in sh_mobile_lcdc_overlay_pan()
1385 /* If the Y offset hasn't changed, the C offset hasn't either. There's in sh_mobile_lcdc_overlay_pan()
1388 if (y_offset == ovl->pan_y_offset) in sh_mobile_lcdc_overlay_pan()
1392 base_addr_y = ovl->dma_handle + y_offset; in sh_mobile_lcdc_overlay_pan()
1393 base_addr_c = ovl->dma_handle + ovl->xres_virtual * ovl->yres_virtual in sh_mobile_lcdc_overlay_pan()
1396 ovl->base_addr_y = base_addr_y; in sh_mobile_lcdc_overlay_pan()
1397 ovl->base_addr_c = base_addr_c; in sh_mobile_lcdc_overlay_pan()
1398 ovl->pan_y_offset = y_offset; in sh_mobile_lcdc_overlay_pan()
1400 lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); in sh_mobile_lcdc_overlay_pan()
1402 lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); in sh_mobile_lcdc_overlay_pan()
1403 lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); in sh_mobile_lcdc_overlay_pan()
1405 lcdc_write(ovl->channel->lcdc, LDBCR, in sh_mobile_lcdc_overlay_pan()
1406 LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); in sh_mobile_lcdc_overlay_pan()
1414 struct sh_mobile_lcdc_overlay *ovl = info->par; in sh_mobile_lcdc_overlay_ioctl()
1418 return sh_mobile_lcdc_wait_for_vsync(ovl->channel); in sh_mobile_lcdc_overlay_ioctl()
1421 return -ENOIOCTLCMD; in sh_mobile_lcdc_overlay_ioctl()
1433 struct sh_mobile_lcdc_overlay *ovl = info->par; in sh_mobile_lcdc_overlay_set_par()
1435 ovl->format = in sh_mobile_lcdc_overlay_set_par()
1436 sh_mobile_format_info(sh_mobile_format_fourcc(&info->var)); in sh_mobile_lcdc_overlay_set_par()
1438 ovl->xres = info->var.xres; in sh_mobile_lcdc_overlay_set_par()
1439 ovl->xres_virtual = info->var.xres_virtual; in sh_mobile_lcdc_overlay_set_par()
1440 ovl->yres = info->var.yres; in sh_mobile_lcdc_overlay_set_par()
1441 ovl->yres_virtual = info->var.yres_virtual; in sh_mobile_lcdc_overlay_set_par()
1443 if (ovl->format->yuv) in sh_mobile_lcdc_overlay_set_par()
1444 ovl->pitch = info->var.xres_virtual; in sh_mobile_lcdc_overlay_set_par()
1446 ovl->pitch = info->var.xres_virtual * ovl->format->bpp / 8; in sh_mobile_lcdc_overlay_set_par()
1450 info->fix.line_length = ovl->pitch; in sh_mobile_lcdc_overlay_set_par()
1452 if (sh_mobile_format_is_fourcc(&info->var)) { in sh_mobile_lcdc_overlay_set_par()
1453 info->fix.type = FB_TYPE_FOURCC; in sh_mobile_lcdc_overlay_set_par()
1454 info->fix.visual = FB_VISUAL_FOURCC; in sh_mobile_lcdc_overlay_set_par()
1456 info->fix.type = FB_TYPE_PACKED_PIXELS; in sh_mobile_lcdc_overlay_set_par()
1457 info->fix.visual = FB_VISUAL_TRUECOLOR; in sh_mobile_lcdc_overlay_set_par()
1466 struct sh_mobile_lcdc_overlay *ovl = info->par; in sh_mobile_lcdc_overlay_blank()
1468 ovl->enabled = !blank; in sh_mobile_lcdc_overlay_blank()
1472 * a non-zero value. in sh_mobile_lcdc_overlay_blank()
1480 struct sh_mobile_lcdc_overlay *ovl = info->par; in sh_mobile_lcdc_overlay_mmap()
1482 if (info->fbdefio) in sh_mobile_lcdc_overlay_mmap()
1485 vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); in sh_mobile_lcdc_overlay_mmap()
1487 return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem, in sh_mobile_lcdc_overlay_mmap()
1488 ovl->dma_handle, ovl->fb_size); in sh_mobile_lcdc_overlay_mmap()
1506 struct fb_info *info = ovl->info; in sh_mobile_lcdc_overlay_fb_unregister()
1508 if (info == NULL || info->dev == NULL) in sh_mobile_lcdc_overlay_fb_unregister()
1511 unregister_framebuffer(ovl->info); in sh_mobile_lcdc_overlay_fb_unregister()
1517 struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc; in sh_mobile_lcdc_overlay_fb_register()
1518 struct fb_info *info = ovl->info; in sh_mobile_lcdc_overlay_fb_register()
1529 dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n", in sh_mobile_lcdc_overlay_fb_register()
1530 dev_name(lcdc->dev), ovl->index, info->var.xres, in sh_mobile_lcdc_overlay_fb_register()
1531 info->var.yres, info->var.bits_per_pixel); in sh_mobile_lcdc_overlay_fb_register()
1534 ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]); in sh_mobile_lcdc_overlay_fb_register()
1545 struct fb_info *info = ovl->info; in sh_mobile_lcdc_overlay_fb_cleanup()
1547 if (info == NULL || info->device == NULL) in sh_mobile_lcdc_overlay_fb_cleanup()
1556 struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc; in sh_mobile_lcdc_overlay_fb_init()
1561 info = framebuffer_alloc(0, priv->dev); in sh_mobile_lcdc_overlay_fb_init()
1563 return -ENOMEM; in sh_mobile_lcdc_overlay_fb_init()
1565 ovl->info = info; in sh_mobile_lcdc_overlay_fb_init()
1567 info->fbops = &sh_mobile_lcdc_overlay_ops; in sh_mobile_lcdc_overlay_fb_init()
1568 info->device = priv->dev; in sh_mobile_lcdc_overlay_fb_init()
1569 info->flags |= FBINFO_VIRTFB; in sh_mobile_lcdc_overlay_fb_init()
1570 info->screen_buffer = ovl->fb_mem; in sh_mobile_lcdc_overlay_fb_init()
1571 info->par = ovl; in sh_mobile_lcdc_overlay_fb_init()
1576 info->fix = sh_mobile_lcdc_overlay_fix; in sh_mobile_lcdc_overlay_fb_init()
1577 snprintf(info->fix.id, sizeof(info->fix.id), in sh_mobile_lcdc_overlay_fb_init()
1578 "SHMobile ovl %u", ovl->index); in sh_mobile_lcdc_overlay_fb_init()
1579 info->fix.smem_start = ovl->dma_handle; in sh_mobile_lcdc_overlay_fb_init()
1580 info->fix.smem_len = ovl->fb_size; in sh_mobile_lcdc_overlay_fb_init()
1581 info->fix.line_length = ovl->pitch; in sh_mobile_lcdc_overlay_fb_init()
1583 if (ovl->format->yuv) in sh_mobile_lcdc_overlay_fb_init()
1584 info->fix.visual = FB_VISUAL_FOURCC; in sh_mobile_lcdc_overlay_fb_init()
1586 info->fix.visual = FB_VISUAL_TRUECOLOR; in sh_mobile_lcdc_overlay_fb_init()
1588 switch (ovl->format->fourcc) { in sh_mobile_lcdc_overlay_fb_init()
1591 info->fix.ypanstep = 2; in sh_mobile_lcdc_overlay_fb_init()
1595 info->fix.xpanstep = 2; in sh_mobile_lcdc_overlay_fb_init()
1599 var = &info->var; in sh_mobile_lcdc_overlay_fb_init()
1601 var->xres = ovl->xres; in sh_mobile_lcdc_overlay_fb_init()
1602 var->yres = ovl->yres; in sh_mobile_lcdc_overlay_fb_init()
1603 var->xres_virtual = ovl->xres_virtual; in sh_mobile_lcdc_overlay_fb_init()
1604 var->yres_virtual = ovl->yres_virtual; in sh_mobile_lcdc_overlay_fb_init()
1605 var->activate = FB_ACTIVATE_NOW; in sh_mobile_lcdc_overlay_fb_init()
1610 if (!ovl->format->yuv) in sh_mobile_lcdc_overlay_fb_init()
1611 var->bits_per_pixel = ovl->format->bpp; in sh_mobile_lcdc_overlay_fb_init()
1613 var->grayscale = ovl->format->fourcc; in sh_mobile_lcdc_overlay_fb_init()
1618 /* -----------------------------------------------------------------------------
1619 * Frame buffer operations - main frame buffer
1626 u32 *palette = info->pseudo_palette; in sh_mobile_lcdc_setcolreg()
1629 return -EINVAL; in sh_mobile_lcdc_setcolreg()
1633 red >>= 16 - info->var.red.length; in sh_mobile_lcdc_setcolreg()
1634 green >>= 16 - info->var.green.length; in sh_mobile_lcdc_setcolreg()
1635 blue >>= 16 - info->var.blue.length; in sh_mobile_lcdc_setcolreg()
1636 transp >>= 16 - info->var.transp.length; in sh_mobile_lcdc_setcolreg()
1638 palette[regno] = (red << info->var.red.offset) | in sh_mobile_lcdc_setcolreg()
1639 (green << info->var.green.offset) | in sh_mobile_lcdc_setcolreg()
1640 (blue << info->var.blue.offset) | in sh_mobile_lcdc_setcolreg()
1641 (transp << info->var.transp.offset); in sh_mobile_lcdc_setcolreg()
1681 struct sh_mobile_lcdc_chan *ch = info->par; in sh_mobile_lcdc_pan()
1682 struct sh_mobile_lcdc_priv *priv = ch->lcdc; in sh_mobile_lcdc_pan()
1688 if (!ch->format->yuv) { in sh_mobile_lcdc_pan()
1689 y_offset = (var->yoffset * ch->xres_virtual + var->xoffset) in sh_mobile_lcdc_pan()
1690 * ch->format->bpp / 8; in sh_mobile_lcdc_pan()
1693 unsigned int xsub = ch->format->bpp < 24 ? 2 : 1; in sh_mobile_lcdc_pan()
1694 unsigned int ysub = ch->format->bpp < 16 ? 2 : 1; in sh_mobile_lcdc_pan()
1696 y_offset = var->yoffset * ch->xres_virtual + var->xoffset; in sh_mobile_lcdc_pan()
1697 c_offset = var->yoffset / ysub * ch->xres_virtual * 2 / xsub in sh_mobile_lcdc_pan()
1698 + var->xoffset * 2 / xsub; in sh_mobile_lcdc_pan()
1701 /* If the Y offset hasn't changed, the C offset hasn't either. There's in sh_mobile_lcdc_pan()
1704 if (y_offset == ch->pan_y_offset) in sh_mobile_lcdc_pan()
1708 base_addr_y = ch->dma_handle + y_offset; in sh_mobile_lcdc_pan()
1709 base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual in sh_mobile_lcdc_pan()
1712 ch->base_addr_y = base_addr_y; in sh_mobile_lcdc_pan()
1713 ch->base_addr_c = base_addr_c; in sh_mobile_lcdc_pan()
1714 ch->pan_y_offset = y_offset; in sh_mobile_lcdc_pan()
1717 if (ch->format->yuv) in sh_mobile_lcdc_pan()
1722 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); in sh_mobile_lcdc_pan()
1724 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS); in sh_mobile_lcdc_pan()
1735 struct sh_mobile_lcdc_chan *ch = info->par; in sh_mobile_lcdc_ioctl()
1744 retval = -ENOIOCTLCMD; in sh_mobile_lcdc_ioctl()
1752 struct sh_mobile_lcdc_chan *ch = info->par; in sh_mobile_fb_reconfig()
1756 if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par)) in sh_mobile_fb_reconfig()
1760 fb_var_to_videomode(&mode, &info->var); in sh_mobile_fb_reconfig()
1762 if (fb_mode_is_equal(&ch->display.mode, &mode)) in sh_mobile_fb_reconfig()
1765 /* Display has been re-plugged, framebuffer is free now, reconfigure */ in sh_mobile_fb_reconfig()
1766 var = info->var; in sh_mobile_fb_reconfig()
1767 fb_videomode_to_var(&var, &ch->display.mode); in sh_mobile_fb_reconfig()
1768 var.width = ch->display.width; in sh_mobile_fb_reconfig()
1769 var.height = ch->display.height; in sh_mobile_fb_reconfig()
1780 * Locking: both .fb_release() and .fb_open() are called with info->lock held if
1785 struct sh_mobile_lcdc_chan *ch = info->par; in sh_mobile_lcdc_release()
1787 mutex_lock(&ch->open_lock); in sh_mobile_lcdc_release()
1788 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count); in sh_mobile_lcdc_release()
1790 ch->use_count--; in sh_mobile_lcdc_release()
1799 mutex_unlock(&ch->open_lock); in sh_mobile_lcdc_release()
1806 struct sh_mobile_lcdc_chan *ch = info->par; in sh_mobile_lcdc_open()
1808 mutex_lock(&ch->open_lock); in sh_mobile_lcdc_open()
1809 ch->use_count++; in sh_mobile_lcdc_open()
1811 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count); in sh_mobile_lcdc_open()
1812 mutex_unlock(&ch->open_lock); in sh_mobile_lcdc_open()
1820 struct sh_mobile_lcdc_chan *ch = info->par; in sh_mobile_lcdc_check_var()
1821 struct sh_mobile_lcdc_priv *p = ch->lcdc; in sh_mobile_lcdc_check_var()
1822 unsigned int best_dist = (unsigned int)-1; in sh_mobile_lcdc_check_var()
1831 * non-overlapping parts of the two rectangles. in sh_mobile_lcdc_check_var()
1833 for (i = 0; i < ch->cfg->num_modes; ++i) { in sh_mobile_lcdc_check_var()
1834 const struct fb_videomode *mode = &ch->cfg->lcd_modes[i]; in sh_mobile_lcdc_check_var()
1838 if (var->xres > mode->xres || var->yres > mode->yres) in sh_mobile_lcdc_check_var()
1841 dist = var->xres * var->yres + mode->xres * mode->yres in sh_mobile_lcdc_check_var()
1842 - 2 * min(var->xres, mode->xres) in sh_mobile_lcdc_check_var()
1843 * min(var->yres, mode->yres); in sh_mobile_lcdc_check_var()
1846 best_xres = mode->xres; in sh_mobile_lcdc_check_var()
1847 best_yres = mode->yres; in sh_mobile_lcdc_check_var()
1853 if (ch->cfg->num_modes != 0) { in sh_mobile_lcdc_check_var()
1854 if (best_dist == (unsigned int)-1) in sh_mobile_lcdc_check_var()
1855 return -EINVAL; in sh_mobile_lcdc_check_var()
1857 var->xres = best_xres; in sh_mobile_lcdc_check_var()
1858 var->yres = best_yres; in sh_mobile_lcdc_check_var()
1866 if (p->forced_fourcc && in sh_mobile_lcdc_check_var()
1867 p->forced_fourcc != sh_mobile_format_fourcc(var)) in sh_mobile_lcdc_check_var()
1868 return -EINVAL; in sh_mobile_lcdc_check_var()
1875 struct sh_mobile_lcdc_chan *ch = info->par; in sh_mobile_lcdc_set_par()
1878 sh_mobile_lcdc_stop(ch->lcdc); in sh_mobile_lcdc_set_par()
1880 ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var)); in sh_mobile_lcdc_set_par()
1881 ch->colorspace = info->var.colorspace; in sh_mobile_lcdc_set_par()
1883 ch->xres = info->var.xres; in sh_mobile_lcdc_set_par()
1884 ch->xres_virtual = info->var.xres_virtual; in sh_mobile_lcdc_set_par()
1885 ch->yres = info->var.yres; in sh_mobile_lcdc_set_par()
1886 ch->yres_virtual = info->var.yres_virtual; in sh_mobile_lcdc_set_par()
1888 if (ch->format->yuv) in sh_mobile_lcdc_set_par()
1889 ch->pitch = info->var.xres_virtual; in sh_mobile_lcdc_set_par()
1891 ch->pitch = info->var.xres_virtual * ch->format->bpp / 8; in sh_mobile_lcdc_set_par()
1893 ret = sh_mobile_lcdc_start(ch->lcdc); in sh_mobile_lcdc_set_par()
1895 dev_err(info->dev, "%s: unable to restart LCDC\n", __func__); in sh_mobile_lcdc_set_par()
1897 info->fix.line_length = ch->pitch; in sh_mobile_lcdc_set_par()
1899 if (sh_mobile_format_is_fourcc(&info->var)) { in sh_mobile_lcdc_set_par()
1900 info->fix.type = FB_TYPE_FOURCC; in sh_mobile_lcdc_set_par()
1901 info->fix.visual = FB_VISUAL_FOURCC; in sh_mobile_lcdc_set_par()
1903 info->fix.type = FB_TYPE_PACKED_PIXELS; in sh_mobile_lcdc_set_par()
1904 info->fix.visual = FB_VISUAL_TRUECOLOR; in sh_mobile_lcdc_set_par()
1920 struct sh_mobile_lcdc_chan *ch = info->par; in sh_mobile_lcdc_blank()
1921 struct sh_mobile_lcdc_priv *p = ch->lcdc; in sh_mobile_lcdc_blank()
1924 if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) { in sh_mobile_lcdc_blank()
1926 .width = ch->xres, in sh_mobile_lcdc_blank()
1927 .height = ch->yres, in sh_mobile_lcdc_blank()
1932 if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) { in sh_mobile_lcdc_blank()
1936 if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) { in sh_mobile_lcdc_blank()
1942 if (!info->fbdefio) { in sh_mobile_lcdc_blank()
1949 ch->blank_status = blank; in sh_mobile_lcdc_blank()
1956 struct sh_mobile_lcdc_chan *ch = info->par; in sh_mobile_lcdc_mmap()
1958 if (info->fbdefio) in sh_mobile_lcdc_mmap()
1961 vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); in sh_mobile_lcdc_mmap()
1963 return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem, in sh_mobile_lcdc_mmap()
1964 ch->dma_handle, ch->fb_size); in sh_mobile_lcdc_mmap()
1987 if (ch->info && ch->info->dev) in sh_mobile_lcdc_channel_fb_unregister()
1988 unregister_framebuffer(ch->info); in sh_mobile_lcdc_channel_fb_unregister()
1994 struct fb_info *info = ch->info; in sh_mobile_lcdc_channel_fb_register()
1997 if (info->fbdefio) { in sh_mobile_lcdc_channel_fb_register()
1998 ch->sglist = vmalloc(sizeof(struct scatterlist) * in sh_mobile_lcdc_channel_fb_register()
1999 ch->fb_size >> PAGE_SHIFT); in sh_mobile_lcdc_channel_fb_register()
2000 if (!ch->sglist) in sh_mobile_lcdc_channel_fb_register()
2001 return -ENOMEM; in sh_mobile_lcdc_channel_fb_register()
2004 info->bl_dev = ch->bl; in sh_mobile_lcdc_channel_fb_register()
2010 dev_info(ch->lcdc->dev, "registered %s/%s as %dx%d %dbpp.\n", in sh_mobile_lcdc_channel_fb_register()
2011 dev_name(ch->lcdc->dev), (ch->cfg->chan == LCDC_CHAN_MAINLCD) ? in sh_mobile_lcdc_channel_fb_register()
2012 "mainlcd" : "sublcd", info->var.xres, info->var.yres, in sh_mobile_lcdc_channel_fb_register()
2013 info->var.bits_per_pixel); in sh_mobile_lcdc_channel_fb_register()
2016 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED) in sh_mobile_lcdc_channel_fb_register()
2017 sh_mobile_lcdc_clk_off(ch->lcdc); in sh_mobile_lcdc_channel_fb_register()
2025 struct fb_info *info = ch->info; in sh_mobile_lcdc_channel_fb_cleanup()
2027 if (!info || !info->device) in sh_mobile_lcdc_channel_fb_cleanup()
2030 vfree(ch->sglist); in sh_mobile_lcdc_channel_fb_cleanup()
2032 fb_dealloc_cmap(&info->cmap); in sh_mobile_lcdc_channel_fb_cleanup()
2041 struct sh_mobile_lcdc_priv *priv = ch->lcdc; in sh_mobile_lcdc_channel_fb_init()
2049 info = framebuffer_alloc(0, priv->dev); in sh_mobile_lcdc_channel_fb_init()
2051 return -ENOMEM; in sh_mobile_lcdc_channel_fb_init()
2053 ch->info = info; in sh_mobile_lcdc_channel_fb_init()
2055 info->fbops = &sh_mobile_lcdc_ops; in sh_mobile_lcdc_channel_fb_init()
2056 info->device = priv->dev; in sh_mobile_lcdc_channel_fb_init()
2057 info->flags |= FBINFO_VIRTFB; in sh_mobile_lcdc_channel_fb_init()
2058 info->screen_buffer = ch->fb_mem; in sh_mobile_lcdc_channel_fb_init()
2059 info->pseudo_palette = &ch->pseudo_palette; in sh_mobile_lcdc_channel_fb_init()
2060 info->par = ch; in sh_mobile_lcdc_channel_fb_init()
2062 fb_videomode_to_modelist(modes, num_modes, &info->modelist); in sh_mobile_lcdc_channel_fb_init()
2064 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); in sh_mobile_lcdc_channel_fb_init()
2066 dev_err(priv->dev, "unable to allocate cmap\n"); in sh_mobile_lcdc_channel_fb_init()
2073 info->fix = sh_mobile_lcdc_fix; in sh_mobile_lcdc_channel_fb_init()
2074 info->fix.smem_start = ch->dma_handle; in sh_mobile_lcdc_channel_fb_init()
2075 info->fix.smem_len = ch->fb_size; in sh_mobile_lcdc_channel_fb_init()
2076 info->fix.line_length = ch->pitch; in sh_mobile_lcdc_channel_fb_init()
2078 if (ch->format->yuv) in sh_mobile_lcdc_channel_fb_init()
2079 info->fix.visual = FB_VISUAL_FOURCC; in sh_mobile_lcdc_channel_fb_init()
2081 info->fix.visual = FB_VISUAL_TRUECOLOR; in sh_mobile_lcdc_channel_fb_init()
2083 switch (ch->format->fourcc) { in sh_mobile_lcdc_channel_fb_init()
2086 info->fix.ypanstep = 2; in sh_mobile_lcdc_channel_fb_init()
2090 info->fix.xpanstep = 2; in sh_mobile_lcdc_channel_fb_init()
2096 var = &info->var; in sh_mobile_lcdc_channel_fb_init()
2098 var->width = ch->display.width; in sh_mobile_lcdc_channel_fb_init()
2099 var->height = ch->display.height; in sh_mobile_lcdc_channel_fb_init()
2100 var->xres_virtual = ch->xres_virtual; in sh_mobile_lcdc_channel_fb_init()
2101 var->yres_virtual = ch->yres_virtual; in sh_mobile_lcdc_channel_fb_init()
2102 var->activate = FB_ACTIVATE_NOW; in sh_mobile_lcdc_channel_fb_init()
2107 if (!ch->format->yuv) in sh_mobile_lcdc_channel_fb_init()
2108 var->bits_per_pixel = ch->format->bpp; in sh_mobile_lcdc_channel_fb_init()
2110 var->grayscale = ch->format->fourcc; in sh_mobile_lcdc_channel_fb_init()
2119 /* -----------------------------------------------------------------------------
2128 ch->bl_brightness = brightness; in sh_mobile_lcdc_update_bl()
2129 return ch->cfg->bl_info.set_brightness(brightness); in sh_mobile_lcdc_update_bl()
2136 return ch->bl_brightness; in sh_mobile_lcdc_get_brightness()
2148 struct backlight_device *bl; in sh_mobile_lcdc_bl_probe() local
2150 bl = backlight_device_register(ch->cfg->bl_info.name, parent, ch, in sh_mobile_lcdc_bl_probe()
2152 if (IS_ERR(bl)) { in sh_mobile_lcdc_bl_probe()
2154 PTR_ERR(bl)); in sh_mobile_lcdc_bl_probe()
2158 bl->props.max_brightness = ch->cfg->bl_info.max_brightness; in sh_mobile_lcdc_bl_probe()
2159 bl->props.brightness = bl->props.max_brightness; in sh_mobile_lcdc_bl_probe()
2160 backlight_update_status(bl); in sh_mobile_lcdc_bl_probe()
2162 return bl; in sh_mobile_lcdc_bl_probe()
2170 /* -----------------------------------------------------------------------------
2215 /* -----------------------------------------------------------------------------
2219 /* -----------------------------------------------------------------------------
2246 for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) in sh_mobile_lcdc_remove()
2247 sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]); in sh_mobile_lcdc_remove()
2248 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) in sh_mobile_lcdc_remove()
2249 sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]); in sh_mobile_lcdc_remove()
2253 for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) { in sh_mobile_lcdc_remove()
2254 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; in sh_mobile_lcdc_remove()
2258 if (ovl->fb_mem) in sh_mobile_lcdc_remove()
2259 dma_free_coherent(&pdev->dev, ovl->fb_size, in sh_mobile_lcdc_remove()
2260 ovl->fb_mem, ovl->dma_handle); in sh_mobile_lcdc_remove()
2263 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { in sh_mobile_lcdc_remove()
2264 struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; in sh_mobile_lcdc_remove()
2266 if (ch->tx_dev) { in sh_mobile_lcdc_remove()
2267 ch->tx_dev->lcdc = NULL; in sh_mobile_lcdc_remove()
2268 module_put(ch->cfg->tx_dev->dev.driver->owner); in sh_mobile_lcdc_remove()
2273 if (ch->fb_mem) in sh_mobile_lcdc_remove()
2274 dma_free_coherent(&pdev->dev, ch->fb_size, in sh_mobile_lcdc_remove()
2275 ch->fb_mem, ch->dma_handle); in sh_mobile_lcdc_remove()
2278 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { in sh_mobile_lcdc_remove()
2279 struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; in sh_mobile_lcdc_remove()
2281 if (ch->bl) in sh_mobile_lcdc_remove()
2282 sh_mobile_lcdc_bl_remove(ch->bl); in sh_mobile_lcdc_remove()
2283 mutex_destroy(&ch->open_lock); in sh_mobile_lcdc_remove()
2286 if (priv->dot_clk) { in sh_mobile_lcdc_remove()
2287 pm_runtime_disable(&pdev->dev); in sh_mobile_lcdc_remove()
2288 clk_put(priv->dot_clk); in sh_mobile_lcdc_remove()
2291 if (priv->base) in sh_mobile_lcdc_remove()
2292 iounmap(priv->base); in sh_mobile_lcdc_remove()
2294 if (priv->irq) in sh_mobile_lcdc_remove()
2295 free_irq(priv->irq, priv); in sh_mobile_lcdc_remove()
2301 int interface_type = ch->cfg->interface_type; in sh_mobile_lcdc_check_interface()
2324 return -EINVAL; in sh_mobile_lcdc_check_interface()
2330 return -EINVAL; in sh_mobile_lcdc_check_interface()
2335 ch->ldmt1r_value = interface_type; in sh_mobile_lcdc_check_interface()
2343 struct device *dev = ovl->channel->lcdc->dev; in sh_mobile_lcdc_overlay_init()
2346 if (ovl->cfg->fourcc == 0) in sh_mobile_lcdc_overlay_init()
2350 format = sh_mobile_format_info(ovl->cfg->fourcc); in sh_mobile_lcdc_overlay_init()
2352 dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc); in sh_mobile_lcdc_overlay_init()
2353 return -EINVAL; in sh_mobile_lcdc_overlay_init()
2356 ovl->enabled = false; in sh_mobile_lcdc_overlay_init()
2357 ovl->mode = LCDC_OVERLAY_BLEND; in sh_mobile_lcdc_overlay_init()
2358 ovl->alpha = 255; in sh_mobile_lcdc_overlay_init()
2359 ovl->rop3 = 0; in sh_mobile_lcdc_overlay_init()
2360 ovl->pos_x = 0; in sh_mobile_lcdc_overlay_init()
2361 ovl->pos_y = 0; in sh_mobile_lcdc_overlay_init()
2364 * double-buffering. in sh_mobile_lcdc_overlay_init()
2366 ovl->format = format; in sh_mobile_lcdc_overlay_init()
2367 ovl->xres = ovl->cfg->max_xres; in sh_mobile_lcdc_overlay_init()
2368 ovl->xres_virtual = ovl->xres; in sh_mobile_lcdc_overlay_init()
2369 ovl->yres = ovl->cfg->max_yres; in sh_mobile_lcdc_overlay_init()
2370 ovl->yres_virtual = ovl->yres * 2; in sh_mobile_lcdc_overlay_init()
2372 if (!format->yuv) in sh_mobile_lcdc_overlay_init()
2373 ovl->pitch = ovl->xres_virtual * format->bpp / 8; in sh_mobile_lcdc_overlay_init()
2375 ovl->pitch = ovl->xres_virtual; in sh_mobile_lcdc_overlay_init()
2378 ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres in sh_mobile_lcdc_overlay_init()
2379 * format->bpp / 8 * 2; in sh_mobile_lcdc_overlay_init()
2380 ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle, in sh_mobile_lcdc_overlay_init()
2382 if (!ovl->fb_mem) { in sh_mobile_lcdc_overlay_init()
2384 return -ENOMEM; in sh_mobile_lcdc_overlay_init()
2398 const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg; in sh_mobile_lcdc_channel_init()
2399 struct device *dev = ch->lcdc->dev; in sh_mobile_lcdc_channel_init()
2407 format = sh_mobile_format_info(cfg->fourcc); in sh_mobile_lcdc_channel_init()
2409 dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc); in sh_mobile_lcdc_channel_init()
2410 return -EINVAL; in sh_mobile_lcdc_channel_init()
2419 for (i = 0, mode = cfg->lcd_modes; i < cfg->num_modes; i++, mode++) { in sh_mobile_lcdc_channel_init()
2420 unsigned int size = mode->yres * mode->xres; in sh_mobile_lcdc_channel_init()
2423 if ((cfg->fourcc == V4L2_PIX_FMT_NV12 || in sh_mobile_lcdc_channel_init()
2424 cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) { in sh_mobile_lcdc_channel_init()
2427 return -EINVAL; in sh_mobile_lcdc_channel_init()
2440 max_mode->xres, max_mode->yres); in sh_mobile_lcdc_channel_init()
2442 if (cfg->lcd_modes == NULL) { in sh_mobile_lcdc_channel_init()
2446 mode = cfg->lcd_modes; in sh_mobile_lcdc_channel_init()
2447 num_modes = cfg->num_modes; in sh_mobile_lcdc_channel_init()
2451 * twice the panel size to allow for double-buffering. in sh_mobile_lcdc_channel_init()
2453 ch->format = format; in sh_mobile_lcdc_channel_init()
2454 ch->xres = mode->xres; in sh_mobile_lcdc_channel_init()
2455 ch->xres_virtual = mode->xres; in sh_mobile_lcdc_channel_init()
2456 ch->yres = mode->yres; in sh_mobile_lcdc_channel_init()
2457 ch->yres_virtual = mode->yres * 2; in sh_mobile_lcdc_channel_init()
2459 if (!format->yuv) { in sh_mobile_lcdc_channel_init()
2460 ch->colorspace = V4L2_COLORSPACE_SRGB; in sh_mobile_lcdc_channel_init()
2461 ch->pitch = ch->xres_virtual * format->bpp / 8; in sh_mobile_lcdc_channel_init()
2463 ch->colorspace = V4L2_COLORSPACE_REC709; in sh_mobile_lcdc_channel_init()
2464 ch->pitch = ch->xres_virtual; in sh_mobile_lcdc_channel_init()
2467 ch->display.width = cfg->panel_cfg.width; in sh_mobile_lcdc_channel_init()
2468 ch->display.height = cfg->panel_cfg.height; in sh_mobile_lcdc_channel_init()
2469 ch->display.mode = *mode; in sh_mobile_lcdc_channel_init()
2472 ch->fb_size = max_size * format->bpp / 8 * 2; in sh_mobile_lcdc_channel_init()
2473 ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle, in sh_mobile_lcdc_channel_init()
2475 if (ch->fb_mem == NULL) { in sh_mobile_lcdc_channel_init()
2477 return -ENOMEM; in sh_mobile_lcdc_channel_init()
2481 if (cfg->tx_dev) { in sh_mobile_lcdc_channel_init()
2482 if (!cfg->tx_dev->dev.driver || in sh_mobile_lcdc_channel_init()
2483 !try_module_get(cfg->tx_dev->dev.driver->owner)) { in sh_mobile_lcdc_channel_init()
2485 return -EINVAL; in sh_mobile_lcdc_channel_init()
2487 ch->tx_dev = platform_get_drvdata(cfg->tx_dev); in sh_mobile_lcdc_channel_init()
2488 ch->tx_dev->lcdc = ch; in sh_mobile_lcdc_channel_init()
2489 ch->tx_dev->def_mode = *mode; in sh_mobile_lcdc_channel_init()
2497 struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; in sh_mobile_lcdc_probe()
2505 dev_err(&pdev->dev, "no platform data defined\n"); in sh_mobile_lcdc_probe()
2506 return -EINVAL; in sh_mobile_lcdc_probe()
2512 dev_err(&pdev->dev, "cannot get platform resources\n"); in sh_mobile_lcdc_probe()
2513 return -ENOENT; in sh_mobile_lcdc_probe()
2518 return -ENOMEM; in sh_mobile_lcdc_probe()
2520 priv->dev = &pdev->dev; in sh_mobile_lcdc_probe()
2522 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) in sh_mobile_lcdc_probe()
2523 mutex_init(&priv->ch[i].open_lock); in sh_mobile_lcdc_probe()
2527 dev_name(&pdev->dev), priv); in sh_mobile_lcdc_probe()
2529 dev_err(&pdev->dev, "unable to request irq\n"); in sh_mobile_lcdc_probe()
2533 priv->irq = irq; in sh_mobile_lcdc_probe()
2534 atomic_set(&priv->hw_usecnt, -1); in sh_mobile_lcdc_probe()
2536 for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) { in sh_mobile_lcdc_probe()
2537 struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels; in sh_mobile_lcdc_probe()
2539 ch->lcdc = priv; in sh_mobile_lcdc_probe()
2540 ch->cfg = &pdata->ch[i]; in sh_mobile_lcdc_probe()
2544 dev_err(&pdev->dev, "unsupported interface type\n"); in sh_mobile_lcdc_probe()
2547 init_waitqueue_head(&ch->frame_end_wait); in sh_mobile_lcdc_probe()
2548 init_completion(&ch->vsync_completion); in sh_mobile_lcdc_probe()
2551 if (ch->cfg->bl_info.max_brightness) in sh_mobile_lcdc_probe()
2552 ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch); in sh_mobile_lcdc_probe()
2554 switch (pdata->ch[i].chan) { in sh_mobile_lcdc_probe()
2556 ch->enabled = LDCNT2R_ME; in sh_mobile_lcdc_probe()
2557 ch->reg_offs = lcdc_offs_mainlcd; in sh_mobile_lcdc_probe()
2561 ch->enabled = LDCNT2R_SE; in sh_mobile_lcdc_probe()
2562 ch->reg_offs = lcdc_offs_sublcd; in sh_mobile_lcdc_probe()
2569 dev_err(&pdev->dev, "no channels defined\n"); in sh_mobile_lcdc_probe()
2570 error = -EINVAL; in sh_mobile_lcdc_probe()
2576 priv->forced_fourcc = pdata->ch[0].fourcc; in sh_mobile_lcdc_probe()
2578 priv->base = ioremap(res->start, resource_size(res)); in sh_mobile_lcdc_probe()
2579 if (!priv->base) { in sh_mobile_lcdc_probe()
2580 error = -ENOMEM; in sh_mobile_lcdc_probe()
2584 error = sh_mobile_lcdc_setup_clocks(priv, pdata->clock_source); in sh_mobile_lcdc_probe()
2586 dev_err(&pdev->dev, "unable to setup clocks\n"); in sh_mobile_lcdc_probe()
2591 pm_runtime_enable(&pdev->dev); in sh_mobile_lcdc_probe()
2594 struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; in sh_mobile_lcdc_probe()
2601 for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { in sh_mobile_lcdc_probe()
2602 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; in sh_mobile_lcdc_probe()
2604 ovl->cfg = &pdata->overlays[i]; in sh_mobile_lcdc_probe()
2605 ovl->channel = &priv->ch[0]; in sh_mobile_lcdc_probe()
2614 dev_err(&pdev->dev, "unable to start hardware\n"); in sh_mobile_lcdc_probe()
2619 struct sh_mobile_lcdc_chan *ch = priv->ch + i; in sh_mobile_lcdc_probe()
2626 for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { in sh_mobile_lcdc_probe()
2627 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; in sh_mobile_lcdc_probe()