PM / sleep: Asynchronous threads for suspend_noirq
[linux/fpc-iii.git] / drivers / video / sh_mobile_lcdcfb.c
blob2bcc84ac18c762f7bc7f5acecdb34149192a1308
1 /*
2 * SuperH Mobile LCDC Framebuffer
4 * Copyright (c) 2008 Magnus Damm
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
11 #include <linux/atomic.h>
12 #include <linux/backlight.h>
13 #include <linux/clk.h>
14 #include <linux/console.h>
15 #include <linux/ctype.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/delay.h>
18 #include <linux/gpio.h>
19 #include <linux/init.h>
20 #include <linux/interrupt.h>
21 #include <linux/ioctl.h>
22 #include <linux/kernel.h>
23 #include <linux/mm.h>
24 #include <linux/module.h>
25 #include <linux/platform_device.h>
26 #include <linux/pm_runtime.h>
27 #include <linux/slab.h>
28 #include <linux/videodev2.h>
29 #include <linux/vmalloc.h>
31 #include <video/sh_mobile_lcdc.h>
32 #include <video/sh_mobile_meram.h>
34 #include "sh_mobile_lcdcfb.h"
36 /* ----------------------------------------------------------------------------
37 * Overlay register definitions
40 #define LDBCR 0xb00
41 #define LDBCR_UPC(n) (1 << ((n) + 16))
42 #define LDBCR_UPF(n) (1 << ((n) + 8))
43 #define LDBCR_UPD(n) (1 << ((n) + 0))
44 #define LDBnBSIFR(n) (0xb20 + (n) * 0x20 + 0x00)
45 #define LDBBSIFR_EN (1 << 31)
46 #define LDBBSIFR_VS (1 << 29)
47 #define LDBBSIFR_BRSEL (1 << 28)
48 #define LDBBSIFR_MX (1 << 27)
49 #define LDBBSIFR_MY (1 << 26)
50 #define LDBBSIFR_CV3 (3 << 24)
51 #define LDBBSIFR_CV2 (2 << 24)
52 #define LDBBSIFR_CV1 (1 << 24)
53 #define LDBBSIFR_CV0 (0 << 24)
54 #define LDBBSIFR_CV_MASK (3 << 24)
55 #define LDBBSIFR_LAY_MASK (0xff << 16)
56 #define LDBBSIFR_LAY_SHIFT 16
57 #define LDBBSIFR_ROP3_MASK (0xff << 16)
58 #define LDBBSIFR_ROP3_SHIFT 16
59 #define LDBBSIFR_AL_PL8 (3 << 14)
60 #define LDBBSIFR_AL_PL1 (2 << 14)
61 #define LDBBSIFR_AL_PK (1 << 14)
62 #define LDBBSIFR_AL_1 (0 << 14)
63 #define LDBBSIFR_AL_MASK (3 << 14)
64 #define LDBBSIFR_SWPL (1 << 10)
65 #define LDBBSIFR_SWPW (1 << 9)
66 #define LDBBSIFR_SWPB (1 << 8)
67 #define LDBBSIFR_RY (1 << 7)
68 #define LDBBSIFR_CHRR_420 (2 << 0)
69 #define LDBBSIFR_CHRR_422 (1 << 0)
70 #define LDBBSIFR_CHRR_444 (0 << 0)
71 #define LDBBSIFR_RPKF_ARGB32 (0x00 << 0)
72 #define LDBBSIFR_RPKF_RGB16 (0x03 << 0)
73 #define LDBBSIFR_RPKF_RGB24 (0x0b << 0)
74 #define LDBBSIFR_RPKF_MASK (0x1f << 0)
75 #define LDBnBSSZR(n) (0xb20 + (n) * 0x20 + 0x04)
76 #define LDBBSSZR_BVSS_MASK (0xfff << 16)
77 #define LDBBSSZR_BVSS_SHIFT 16
78 #define LDBBSSZR_BHSS_MASK (0xfff << 0)
79 #define LDBBSSZR_BHSS_SHIFT 0
80 #define LDBnBLOCR(n) (0xb20 + (n) * 0x20 + 0x08)
81 #define LDBBLOCR_CVLC_MASK (0xfff << 16)
82 #define LDBBLOCR_CVLC_SHIFT 16
83 #define LDBBLOCR_CHLC_MASK (0xfff << 0)
84 #define LDBBLOCR_CHLC_SHIFT 0
85 #define LDBnBSMWR(n) (0xb20 + (n) * 0x20 + 0x0c)
86 #define LDBBSMWR_BSMWA_MASK (0xffff << 16)
87 #define LDBBSMWR_BSMWA_SHIFT 16
88 #define LDBBSMWR_BSMW_MASK (0xffff << 0)
89 #define LDBBSMWR_BSMW_SHIFT 0
90 #define LDBnBSAYR(n) (0xb20 + (n) * 0x20 + 0x10)
91 #define LDBBSAYR_FG1A_MASK (0xff << 24)
92 #define LDBBSAYR_FG1A_SHIFT 24
93 #define LDBBSAYR_FG1R_MASK (0xff << 16)
94 #define LDBBSAYR_FG1R_SHIFT 16
95 #define LDBBSAYR_FG1G_MASK (0xff << 8)
96 #define LDBBSAYR_FG1G_SHIFT 8
97 #define LDBBSAYR_FG1B_MASK (0xff << 0)
98 #define LDBBSAYR_FG1B_SHIFT 0
99 #define LDBnBSACR(n) (0xb20 + (n) * 0x20 + 0x14)
100 #define LDBBSACR_FG2A_MASK (0xff << 24)
101 #define LDBBSACR_FG2A_SHIFT 24
102 #define LDBBSACR_FG2R_MASK (0xff << 16)
103 #define LDBBSACR_FG2R_SHIFT 16
104 #define LDBBSACR_FG2G_MASK (0xff << 8)
105 #define LDBBSACR_FG2G_SHIFT 8
106 #define LDBBSACR_FG2B_MASK (0xff << 0)
107 #define LDBBSACR_FG2B_SHIFT 0
108 #define LDBnBSAAR(n) (0xb20 + (n) * 0x20 + 0x18)
109 #define LDBBSAAR_AP_MASK (0xff << 24)
110 #define LDBBSAAR_AP_SHIFT 24
111 #define LDBBSAAR_R_MASK (0xff << 16)
112 #define LDBBSAAR_R_SHIFT 16
113 #define LDBBSAAR_GY_MASK (0xff << 8)
114 #define LDBBSAAR_GY_SHIFT 8
115 #define LDBBSAAR_B_MASK (0xff << 0)
116 #define LDBBSAAR_B_SHIFT 0
117 #define LDBnBPPCR(n) (0xb20 + (n) * 0x20 + 0x1c)
118 #define LDBBPPCR_AP_MASK (0xff << 24)
119 #define LDBBPPCR_AP_SHIFT 24
120 #define LDBBPPCR_R_MASK (0xff << 16)
121 #define LDBBPPCR_R_SHIFT 16
122 #define LDBBPPCR_GY_MASK (0xff << 8)
123 #define LDBBPPCR_GY_SHIFT 8
124 #define LDBBPPCR_B_MASK (0xff << 0)
125 #define LDBBPPCR_B_SHIFT 0
126 #define LDBnBBGCL(n) (0xb10 + (n) * 0x04)
127 #define LDBBBGCL_BGA_MASK (0xff << 24)
128 #define LDBBBGCL_BGA_SHIFT 24
129 #define LDBBBGCL_BGR_MASK (0xff << 16)
130 #define LDBBBGCL_BGR_SHIFT 16
131 #define LDBBBGCL_BGG_MASK (0xff << 8)
132 #define LDBBBGCL_BGG_SHIFT 8
133 #define LDBBBGCL_BGB_MASK (0xff << 0)
134 #define LDBBBGCL_BGB_SHIFT 0
136 #define SIDE_B_OFFSET 0x1000
137 #define MIRROR_OFFSET 0x2000
139 #define MAX_XRES 1920
140 #define MAX_YRES 1080
142 enum sh_mobile_lcdc_overlay_mode {
143 LCDC_OVERLAY_BLEND,
144 LCDC_OVERLAY_ROP3,
148 * struct sh_mobile_lcdc_overlay - LCDC display overlay
150 * @channel: LCDC channel this overlay belongs to
151 * @cfg: Overlay configuration
152 * @info: Frame buffer device
153 * @index: Overlay index (0-3)
154 * @base: Overlay registers base address
155 * @enabled: True if the overlay is enabled
156 * @mode: Overlay blending mode (alpha blend or ROP3)
157 * @alpha: Global alpha blending value (0-255, for alpha blending mode)
158 * @rop3: Raster operation (for ROP3 mode)
159 * @fb_mem: Frame buffer virtual memory address
160 * @fb_size: Frame buffer size in bytes
161 * @dma_handle: Frame buffer DMA address
162 * @base_addr_y: Overlay base address (RGB or luma component)
163 * @base_addr_c: Overlay base address (chroma component)
164 * @pan_y_offset: Panning linear offset in bytes (luma component)
165 * @format: Current pixelf format
166 * @xres: Horizontal visible resolution
167 * @xres_virtual: Horizontal total resolution
168 * @yres: Vertical visible resolution
169 * @yres_virtual: Vertical total resolution
170 * @pitch: Overlay line pitch
171 * @pos_x: Horizontal overlay position
172 * @pos_y: Vertical overlay position
174 struct sh_mobile_lcdc_overlay {
175 struct sh_mobile_lcdc_chan *channel;
177 const struct sh_mobile_lcdc_overlay_cfg *cfg;
178 struct fb_info *info;
180 unsigned int index;
181 unsigned long base;
183 bool enabled;
184 enum sh_mobile_lcdc_overlay_mode mode;
185 unsigned int alpha;
186 unsigned int rop3;
188 void *fb_mem;
189 unsigned long fb_size;
191 dma_addr_t dma_handle;
192 unsigned long base_addr_y;
193 unsigned long base_addr_c;
194 unsigned long pan_y_offset;
196 const struct sh_mobile_lcdc_format_info *format;
197 unsigned int xres;
198 unsigned int xres_virtual;
199 unsigned int yres;
200 unsigned int yres_virtual;
201 unsigned int pitch;
202 int pos_x;
203 int pos_y;
206 struct sh_mobile_lcdc_priv {
207 void __iomem *base;
208 int irq;
209 atomic_t hw_usecnt;
210 struct device *dev;
211 struct clk *dot_clk;
212 unsigned long lddckr;
214 struct sh_mobile_lcdc_chan ch[2];
215 struct sh_mobile_lcdc_overlay overlays[4];
217 struct notifier_block notifier;
218 int started;
219 int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
220 struct sh_mobile_meram_info *meram_dev;
223 /* -----------------------------------------------------------------------------
224 * Registers access
227 static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
228 [LDDCKPAT1R] = 0x400,
229 [LDDCKPAT2R] = 0x404,
230 [LDMT1R] = 0x418,
231 [LDMT2R] = 0x41c,
232 [LDMT3R] = 0x420,
233 [LDDFR] = 0x424,
234 [LDSM1R] = 0x428,
235 [LDSM2R] = 0x42c,
236 [LDSA1R] = 0x430,
237 [LDSA2R] = 0x434,
238 [LDMLSR] = 0x438,
239 [LDHCNR] = 0x448,
240 [LDHSYNR] = 0x44c,
241 [LDVLNR] = 0x450,
242 [LDVSYNR] = 0x454,
243 [LDPMR] = 0x460,
244 [LDHAJR] = 0x4a0,
247 static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
248 [LDDCKPAT1R] = 0x408,
249 [LDDCKPAT2R] = 0x40c,
250 [LDMT1R] = 0x600,
251 [LDMT2R] = 0x604,
252 [LDMT3R] = 0x608,
253 [LDDFR] = 0x60c,
254 [LDSM1R] = 0x610,
255 [LDSM2R] = 0x614,
256 [LDSA1R] = 0x618,
257 [LDMLSR] = 0x620,
258 [LDHCNR] = 0x624,
259 [LDHSYNR] = 0x628,
260 [LDVLNR] = 0x62c,
261 [LDVSYNR] = 0x630,
262 [LDPMR] = 0x63c,
265 static bool banked(int reg_nr)
267 switch (reg_nr) {
268 case LDMT1R:
269 case LDMT2R:
270 case LDMT3R:
271 case LDDFR:
272 case LDSM1R:
273 case LDSA1R:
274 case LDSA2R:
275 case LDMLSR:
276 case LDHCNR:
277 case LDHSYNR:
278 case LDVLNR:
279 case LDVSYNR:
280 return true;
282 return false;
285 static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
287 return chan->cfg->chan == LCDC_CHAN_SUBLCD;
290 static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
291 int reg_nr, unsigned long data)
293 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]);
294 if (banked(reg_nr))
295 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
296 SIDE_B_OFFSET);
299 static void lcdc_write_chan_mirror(struct sh_mobile_lcdc_chan *chan,
300 int reg_nr, unsigned long data)
302 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
303 MIRROR_OFFSET);
306 static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
307 int reg_nr)
309 return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
312 static void lcdc_write_overlay(struct sh_mobile_lcdc_overlay *ovl,
313 int reg, unsigned long data)
315 iowrite32(data, ovl->channel->lcdc->base + reg);
316 iowrite32(data, ovl->channel->lcdc->base + reg + SIDE_B_OFFSET);
319 static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
320 unsigned long reg_offs, unsigned long data)
322 iowrite32(data, priv->base + reg_offs);
325 static unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv,
326 unsigned long reg_offs)
328 return ioread32(priv->base + reg_offs);
331 static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
332 unsigned long reg_offs,
333 unsigned long mask, unsigned long until)
335 while ((lcdc_read(priv, reg_offs) & mask) != until)
336 cpu_relax();
339 /* -----------------------------------------------------------------------------
340 * Clock management
343 static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
345 if (atomic_inc_and_test(&priv->hw_usecnt)) {
346 if (priv->dot_clk)
347 clk_prepare_enable(priv->dot_clk);
348 pm_runtime_get_sync(priv->dev);
349 if (priv->meram_dev && priv->meram_dev->pdev)
350 pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
354 static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
356 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
357 if (priv->meram_dev && priv->meram_dev->pdev)
358 pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
359 pm_runtime_put(priv->dev);
360 if (priv->dot_clk)
361 clk_disable_unprepare(priv->dot_clk);
365 static int sh_mobile_lcdc_setup_clocks(struct sh_mobile_lcdc_priv *priv,
366 int clock_source)
368 struct clk *clk;
369 char *str;
371 switch (clock_source) {
372 case LCDC_CLK_BUS:
373 str = "bus_clk";
374 priv->lddckr = LDDCKR_ICKSEL_BUS;
375 break;
376 case LCDC_CLK_PERIPHERAL:
377 str = "peripheral_clk";
378 priv->lddckr = LDDCKR_ICKSEL_MIPI;
379 break;
380 case LCDC_CLK_EXTERNAL:
381 str = NULL;
382 priv->lddckr = LDDCKR_ICKSEL_HDMI;
383 break;
384 default:
385 return -EINVAL;
388 if (str == NULL)
389 return 0;
391 clk = clk_get(priv->dev, str);
392 if (IS_ERR(clk)) {
393 dev_err(priv->dev, "cannot get dot clock %s\n", str);
394 return PTR_ERR(clk);
397 priv->dot_clk = clk;
398 return 0;
401 /* -----------------------------------------------------------------------------
402 * Display, panel and deferred I/O
405 static void lcdc_sys_write_index(void *handle, unsigned long data)
407 struct sh_mobile_lcdc_chan *ch = handle;
409 lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT);
410 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
411 lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
412 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
413 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
416 static void lcdc_sys_write_data(void *handle, unsigned long data)
418 struct sh_mobile_lcdc_chan *ch = handle;
420 lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW);
421 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
422 lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
423 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
424 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
427 static unsigned long lcdc_sys_read_data(void *handle)
429 struct sh_mobile_lcdc_chan *ch = handle;
431 lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR);
432 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
433 lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA |
434 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
435 udelay(1);
436 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
438 return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
441 static struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
442 lcdc_sys_write_index,
443 lcdc_sys_write_data,
444 lcdc_sys_read_data,
447 static int sh_mobile_lcdc_sginit(struct fb_info *info,
448 struct list_head *pagelist)
450 struct sh_mobile_lcdc_chan *ch = info->par;
451 unsigned int nr_pages_max = ch->fb_size >> PAGE_SHIFT;
452 struct page *page;
453 int nr_pages = 0;
455 sg_init_table(ch->sglist, nr_pages_max);
457 list_for_each_entry(page, pagelist, lru)
458 sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0);
460 return nr_pages;
463 static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
464 struct list_head *pagelist)
466 struct sh_mobile_lcdc_chan *ch = info->par;
467 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
469 /* enable clocks before accessing hardware */
470 sh_mobile_lcdc_clk_on(ch->lcdc);
473 * It's possible to get here without anything on the pagelist via
474 * sh_mobile_lcdc_deferred_io_touch() or via a userspace fsync()
475 * invocation. In the former case, the acceleration routines are
476 * stepped in to when using the framebuffer console causing the
477 * workqueue to be scheduled without any dirty pages on the list.
479 * Despite this, a panel update is still needed given that the
480 * acceleration routines have their own methods for writing in
481 * that still need to be updated.
483 * The fsync() and empty pagelist case could be optimized for,
484 * but we don't bother, as any application exhibiting such
485 * behaviour is fundamentally broken anyways.
487 if (!list_empty(pagelist)) {
488 unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
490 /* trigger panel update */
491 dma_map_sg(ch->lcdc->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
492 if (panel->start_transfer)
493 panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
494 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
495 dma_unmap_sg(ch->lcdc->dev, ch->sglist, nr_pages,
496 DMA_TO_DEVICE);
497 } else {
498 if (panel->start_transfer)
499 panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
500 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
504 static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
506 struct fb_deferred_io *fbdefio = info->fbdefio;
508 if (fbdefio)
509 schedule_delayed_work(&info->deferred_work, fbdefio->delay);
512 static void sh_mobile_lcdc_display_on(struct sh_mobile_lcdc_chan *ch)
514 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
516 if (ch->tx_dev) {
517 int ret;
519 ret = ch->tx_dev->ops->display_on(ch->tx_dev);
520 if (ret < 0)
521 return;
523 if (ret == SH_MOBILE_LCDC_DISPLAY_DISCONNECTED)
524 ch->info->state = FBINFO_STATE_SUSPENDED;
527 /* HDMI must be enabled before LCDC configuration */
528 if (panel->display_on)
529 panel->display_on();
532 static void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch)
534 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
536 if (panel->display_off)
537 panel->display_off();
539 if (ch->tx_dev)
540 ch->tx_dev->ops->display_off(ch->tx_dev);
543 static bool
544 sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch,
545 const struct fb_videomode *new_mode)
547 dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n",
548 ch->display.mode.xres, ch->display.mode.yres,
549 new_mode->xres, new_mode->yres);
551 /* It can be a different monitor with an equal video-mode */
552 if (fb_mode_is_equal(&ch->display.mode, new_mode))
553 return false;
555 dev_dbg(ch->info->dev, "Switching %u -> %u lines\n",
556 ch->display.mode.yres, new_mode->yres);
557 ch->display.mode = *new_mode;
559 return true;
562 static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
563 struct fb_info *info);
565 static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
566 enum sh_mobile_lcdc_entity_event event,
567 const struct fb_videomode *mode,
568 const struct fb_monspecs *monspec)
570 struct fb_info *info = ch->info;
571 struct fb_var_screeninfo var;
572 int ret = 0;
574 switch (event) {
575 case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT:
576 /* HDMI plug in */
577 console_lock();
578 if (lock_fb_info(info)) {
581 ch->display.width = monspec->max_x * 10;
582 ch->display.height = monspec->max_y * 10;
584 if (!sh_mobile_lcdc_must_reconfigure(ch, mode) &&
585 info->state == FBINFO_STATE_RUNNING) {
586 /* First activation with the default monitor.
587 * Just turn on, if we run a resume here, the
588 * logo disappears.
590 info->var.width = ch->display.width;
591 info->var.height = ch->display.height;
592 sh_mobile_lcdc_display_on(ch);
593 } else {
594 /* New monitor or have to wake up */
595 fb_set_suspend(info, 0);
599 unlock_fb_info(info);
601 console_unlock();
602 break;
604 case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT:
605 /* HDMI disconnect */
606 console_lock();
607 if (lock_fb_info(info)) {
608 fb_set_suspend(info, 1);
609 unlock_fb_info(info);
611 console_unlock();
612 break;
614 case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
615 /* Validate a proposed new mode */
616 fb_videomode_to_var(&var, mode);
617 var.bits_per_pixel = info->var.bits_per_pixel;
618 var.grayscale = info->var.grayscale;
619 ret = sh_mobile_lcdc_check_var(&var, info);
620 break;
623 return ret;
626 /* -----------------------------------------------------------------------------
627 * Format helpers
630 struct sh_mobile_lcdc_format_info {
631 u32 fourcc;
632 unsigned int bpp;
633 bool yuv;
634 u32 lddfr;
637 static const struct sh_mobile_lcdc_format_info sh_mobile_format_infos[] = {
639 .fourcc = V4L2_PIX_FMT_RGB565,
640 .bpp = 16,
641 .yuv = false,
642 .lddfr = LDDFR_PKF_RGB16,
643 }, {
644 .fourcc = V4L2_PIX_FMT_BGR24,
645 .bpp = 24,
646 .yuv = false,
647 .lddfr = LDDFR_PKF_RGB24,
648 }, {
649 .fourcc = V4L2_PIX_FMT_BGR32,
650 .bpp = 32,
651 .yuv = false,
652 .lddfr = LDDFR_PKF_ARGB32,
653 }, {
654 .fourcc = V4L2_PIX_FMT_NV12,
655 .bpp = 12,
656 .yuv = true,
657 .lddfr = LDDFR_CC | LDDFR_YF_420,
658 }, {
659 .fourcc = V4L2_PIX_FMT_NV21,
660 .bpp = 12,
661 .yuv = true,
662 .lddfr = LDDFR_CC | LDDFR_YF_420,
663 }, {
664 .fourcc = V4L2_PIX_FMT_NV16,
665 .bpp = 16,
666 .yuv = true,
667 .lddfr = LDDFR_CC | LDDFR_YF_422,
668 }, {
669 .fourcc = V4L2_PIX_FMT_NV61,
670 .bpp = 16,
671 .yuv = true,
672 .lddfr = LDDFR_CC | LDDFR_YF_422,
673 }, {
674 .fourcc = V4L2_PIX_FMT_NV24,
675 .bpp = 24,
676 .yuv = true,
677 .lddfr = LDDFR_CC | LDDFR_YF_444,
678 }, {
679 .fourcc = V4L2_PIX_FMT_NV42,
680 .bpp = 24,
681 .yuv = true,
682 .lddfr = LDDFR_CC | LDDFR_YF_444,
686 static const struct sh_mobile_lcdc_format_info *
687 sh_mobile_format_info(u32 fourcc)
689 unsigned int i;
691 for (i = 0; i < ARRAY_SIZE(sh_mobile_format_infos); ++i) {
692 if (sh_mobile_format_infos[i].fourcc == fourcc)
693 return &sh_mobile_format_infos[i];
696 return NULL;
699 static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
701 if (var->grayscale > 1)
702 return var->grayscale;
704 switch (var->bits_per_pixel) {
705 case 16:
706 return V4L2_PIX_FMT_RGB565;
707 case 24:
708 return V4L2_PIX_FMT_BGR24;
709 case 32:
710 return V4L2_PIX_FMT_BGR32;
711 default:
712 return 0;
716 static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
718 return var->grayscale > 1;
721 /* -----------------------------------------------------------------------------
722 * Start, stop and IRQ
725 static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
727 struct sh_mobile_lcdc_priv *priv = data;
728 struct sh_mobile_lcdc_chan *ch;
729 unsigned long ldintr;
730 int is_sub;
731 int k;
733 /* Acknowledge interrupts and disable further VSYNC End IRQs. */
734 ldintr = lcdc_read(priv, _LDINTR);
735 lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE);
737 /* figure out if this interrupt is for main or sub lcd */
738 is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0;
740 /* wake up channel and disable clocks */
741 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
742 ch = &priv->ch[k];
744 if (!ch->enabled)
745 continue;
747 /* Frame End */
748 if (ldintr & LDINTR_FS) {
749 if (is_sub == lcdc_chan_is_sublcd(ch)) {
750 ch->frame_end = 1;
751 wake_up(&ch->frame_end_wait);
753 sh_mobile_lcdc_clk_off(priv);
757 /* VSYNC End */
758 if (ldintr & LDINTR_VES)
759 complete(&ch->vsync_completion);
762 return IRQ_HANDLED;
765 static int sh_mobile_lcdc_wait_for_vsync(struct sh_mobile_lcdc_chan *ch)
767 unsigned long ldintr;
768 int ret;
770 /* Enable VSync End interrupt and be careful not to acknowledge any
771 * pending interrupt.
773 ldintr = lcdc_read(ch->lcdc, _LDINTR);
774 ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
775 lcdc_write(ch->lcdc, _LDINTR, ldintr);
777 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
778 msecs_to_jiffies(100));
779 if (!ret)
780 return -ETIMEDOUT;
782 return 0;
785 static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
786 int start)
788 unsigned long tmp = lcdc_read(priv, _LDCNT2R);
789 int k;
791 /* start or stop the lcdc */
792 if (start)
793 lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO);
794 else
795 lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO);
797 /* wait until power is applied/stopped on all channels */
798 for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
799 if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
800 while (1) {
801 tmp = lcdc_read_chan(&priv->ch[k], LDPMR)
802 & LDPMR_LPS;
803 if (start && tmp == LDPMR_LPS)
804 break;
805 if (!start && tmp == 0)
806 break;
807 cpu_relax();
810 if (!start)
811 lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
814 static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
816 const struct fb_var_screeninfo *var = &ch->info->var;
817 const struct fb_videomode *mode = &ch->display.mode;
818 unsigned long h_total, hsync_pos, display_h_total;
819 u32 tmp;
821 tmp = ch->ldmt1r_value;
822 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL;
823 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL;
824 tmp |= (ch->cfg->flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0;
825 tmp |= (ch->cfg->flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0;
826 tmp |= (ch->cfg->flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0;
827 tmp |= (ch->cfg->flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0;
828 tmp |= (ch->cfg->flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0;
829 lcdc_write_chan(ch, LDMT1R, tmp);
831 /* setup SYS bus */
832 lcdc_write_chan(ch, LDMT2R, ch->cfg->sys_bus_cfg.ldmt2r);
833 lcdc_write_chan(ch, LDMT3R, ch->cfg->sys_bus_cfg.ldmt3r);
835 /* horizontal configuration */
836 h_total = mode->xres + mode->hsync_len + mode->left_margin
837 + mode->right_margin;
838 tmp = h_total / 8; /* HTCN */
839 tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */
840 lcdc_write_chan(ch, LDHCNR, tmp);
842 hsync_pos = mode->xres + mode->right_margin;
843 tmp = hsync_pos / 8; /* HSYNP */
844 tmp |= (mode->hsync_len / 8) << 16; /* HSYNW */
845 lcdc_write_chan(ch, LDHSYNR, tmp);
847 /* vertical configuration */
848 tmp = mode->yres + mode->vsync_len + mode->upper_margin
849 + mode->lower_margin; /* VTLN */
850 tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */
851 lcdc_write_chan(ch, LDVLNR, tmp);
853 tmp = mode->yres + mode->lower_margin; /* VSYNP */
854 tmp |= mode->vsync_len << 16; /* VSYNW */
855 lcdc_write_chan(ch, LDVSYNR, tmp);
857 /* Adjust horizontal synchronisation for HDMI */
858 display_h_total = mode->xres + mode->hsync_len + mode->left_margin
859 + mode->right_margin;
860 tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16)
861 | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7);
862 lcdc_write_chan(ch, LDHAJR, tmp);
863 lcdc_write_chan_mirror(ch, LDHAJR, tmp);
866 static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
868 u32 format = 0;
870 if (!ovl->enabled) {
871 lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
872 lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0);
873 lcdc_write(ovl->channel->lcdc, LDBCR,
874 LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
875 return;
878 ovl->base_addr_y = ovl->dma_handle;
879 ovl->base_addr_c = ovl->dma_handle
880 + ovl->xres_virtual * ovl->yres_virtual;
882 switch (ovl->mode) {
883 case LCDC_OVERLAY_BLEND:
884 format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT);
885 break;
887 case LCDC_OVERLAY_ROP3:
888 format = LDBBSIFR_EN | LDBBSIFR_BRSEL
889 | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT);
890 break;
893 switch (ovl->format->fourcc) {
894 case V4L2_PIX_FMT_RGB565:
895 case V4L2_PIX_FMT_NV21:
896 case V4L2_PIX_FMT_NV61:
897 case V4L2_PIX_FMT_NV42:
898 format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW;
899 break;
900 case V4L2_PIX_FMT_BGR24:
901 case V4L2_PIX_FMT_NV12:
902 case V4L2_PIX_FMT_NV16:
903 case V4L2_PIX_FMT_NV24:
904 format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB;
905 break;
906 case V4L2_PIX_FMT_BGR32:
907 default:
908 format |= LDBBSIFR_SWPL;
909 break;
912 switch (ovl->format->fourcc) {
913 case V4L2_PIX_FMT_RGB565:
914 format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16;
915 break;
916 case V4L2_PIX_FMT_BGR24:
917 format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24;
918 break;
919 case V4L2_PIX_FMT_BGR32:
920 format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
921 break;
922 case V4L2_PIX_FMT_NV12:
923 case V4L2_PIX_FMT_NV21:
924 format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420;
925 break;
926 case V4L2_PIX_FMT_NV16:
927 case V4L2_PIX_FMT_NV61:
928 format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422;
929 break;
930 case V4L2_PIX_FMT_NV24:
931 case V4L2_PIX_FMT_NV42:
932 format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444;
933 break;
936 lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
938 lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format);
940 lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index),
941 (ovl->yres << LDBBSSZR_BVSS_SHIFT) |
942 (ovl->xres << LDBBSSZR_BHSS_SHIFT));
943 lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index),
944 (ovl->pos_y << LDBBLOCR_CVLC_SHIFT) |
945 (ovl->pos_x << LDBBLOCR_CHLC_SHIFT));
946 lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index),
947 ovl->pitch << LDBBSMWR_BSMW_SHIFT);
949 lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
950 lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
952 lcdc_write(ovl->channel->lcdc, LDBCR,
953 LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
957 * __sh_mobile_lcdc_start - Configure and start the LCDC
958 * @priv: LCDC device
960 * Configure all enabled channels and start the LCDC device. All external
961 * devices (clocks, MERAM, panels, ...) are not touched by this function.
963 static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
965 struct sh_mobile_lcdc_chan *ch;
966 unsigned long tmp;
967 int k, m;
969 /* Enable LCDC channels. Read data from external memory, avoid using the
970 * BEU for now.
972 lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled);
974 /* Stop the LCDC first and disable all interrupts. */
975 sh_mobile_lcdc_start_stop(priv, 0);
976 lcdc_write(priv, _LDINTR, 0);
978 /* Configure power supply, dot clocks and start them. */
979 tmp = priv->lddckr;
980 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
981 ch = &priv->ch[k];
982 if (!ch->enabled)
983 continue;
985 /* Power supply */
986 lcdc_write_chan(ch, LDPMR, 0);
988 m = ch->cfg->clock_divider;
989 if (!m)
990 continue;
992 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
993 * denominator.
995 lcdc_write_chan(ch, LDDCKPAT1R, 0);
996 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
998 if (m == 1)
999 m = LDDCKR_MOSEL;
1000 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
1003 lcdc_write(priv, _LDDCKR, tmp);
1004 lcdc_write(priv, _LDDCKSTPR, 0);
1005 lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
1007 /* Setup geometry, format, frame buffer memory and operation mode. */
1008 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
1009 ch = &priv->ch[k];
1010 if (!ch->enabled)
1011 continue;
1013 sh_mobile_lcdc_geometry(ch);
1015 tmp = ch->format->lddfr;
1017 if (ch->format->yuv) {
1018 switch (ch->colorspace) {
1019 case V4L2_COLORSPACE_REC709:
1020 tmp |= LDDFR_CF1;
1021 break;
1022 case V4L2_COLORSPACE_JPEG:
1023 tmp |= LDDFR_CF0;
1024 break;
1028 lcdc_write_chan(ch, LDDFR, tmp);
1029 lcdc_write_chan(ch, LDMLSR, ch->line_size);
1030 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
1031 if (ch->format->yuv)
1032 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
1034 /* When using deferred I/O mode, configure the LCDC for one-shot
1035 * operation and enable the frame end interrupt. Otherwise use
1036 * continuous read mode.
1038 if (ch->ldmt1r_value & LDMT1R_IFM &&
1039 ch->cfg->sys_bus_cfg.deferred_io_msec) {
1040 lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
1041 lcdc_write(priv, _LDINTR, LDINTR_FE);
1042 } else {
1043 lcdc_write_chan(ch, LDSM1R, 0);
1047 /* Word and long word swap. */
1048 switch (priv->ch[0].format->fourcc) {
1049 case V4L2_PIX_FMT_RGB565:
1050 case V4L2_PIX_FMT_NV21:
1051 case V4L2_PIX_FMT_NV61:
1052 case V4L2_PIX_FMT_NV42:
1053 tmp = LDDDSR_LS | LDDDSR_WS;
1054 break;
1055 case V4L2_PIX_FMT_BGR24:
1056 case V4L2_PIX_FMT_NV12:
1057 case V4L2_PIX_FMT_NV16:
1058 case V4L2_PIX_FMT_NV24:
1059 tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
1060 break;
1061 case V4L2_PIX_FMT_BGR32:
1062 default:
1063 tmp = LDDDSR_LS;
1064 break;
1066 lcdc_write(priv, _LDDDSR, tmp);
1068 /* Enable the display output. */
1069 lcdc_write(priv, _LDCNT1R, LDCNT1R_DE);
1070 sh_mobile_lcdc_start_stop(priv, 1);
1071 priv->started = 1;
1074 static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
1076 struct sh_mobile_meram_info *mdev = priv->meram_dev;
1077 struct sh_mobile_lcdc_chan *ch;
1078 unsigned long tmp;
1079 int ret;
1080 int k;
1082 /* enable clocks before accessing the hardware */
1083 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
1084 if (priv->ch[k].enabled)
1085 sh_mobile_lcdc_clk_on(priv);
1088 /* reset */
1089 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR);
1090 lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
1092 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
1093 const struct sh_mobile_lcdc_panel_cfg *panel;
1095 ch = &priv->ch[k];
1096 if (!ch->enabled)
1097 continue;
1099 panel = &ch->cfg->panel_cfg;
1100 if (panel->setup_sys) {
1101 ret = panel->setup_sys(ch, &sh_mobile_lcdc_sys_bus_ops);
1102 if (ret)
1103 return ret;
1107 /* Compute frame buffer base address and pitch for each channel. */
1108 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
1109 int pixelformat;
1110 void *cache;
1112 ch = &priv->ch[k];
1113 if (!ch->enabled)
1114 continue;
1116 ch->base_addr_y = ch->dma_handle;
1117 ch->base_addr_c = ch->dma_handle
1118 + ch->xres_virtual * ch->yres_virtual;
1119 ch->line_size = ch->pitch;
1121 /* Enable MERAM if possible. */
1122 if (mdev == NULL || ch->cfg->meram_cfg == NULL)
1123 continue;
1125 /* Free the allocated MERAM cache. */
1126 if (ch->cache) {
1127 sh_mobile_meram_cache_free(mdev, ch->cache);
1128 ch->cache = NULL;
1131 switch (ch->format->fourcc) {
1132 case V4L2_PIX_FMT_NV12:
1133 case V4L2_PIX_FMT_NV21:
1134 case V4L2_PIX_FMT_NV16:
1135 case V4L2_PIX_FMT_NV61:
1136 pixelformat = SH_MOBILE_MERAM_PF_NV;
1137 break;
1138 case V4L2_PIX_FMT_NV24:
1139 case V4L2_PIX_FMT_NV42:
1140 pixelformat = SH_MOBILE_MERAM_PF_NV24;
1141 break;
1142 case V4L2_PIX_FMT_RGB565:
1143 case V4L2_PIX_FMT_BGR24:
1144 case V4L2_PIX_FMT_BGR32:
1145 default:
1146 pixelformat = SH_MOBILE_MERAM_PF_RGB;
1147 break;
1150 cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg,
1151 ch->pitch, ch->yres, pixelformat,
1152 &ch->line_size);
1153 if (!IS_ERR(cache)) {
1154 sh_mobile_meram_cache_update(mdev, cache,
1155 ch->base_addr_y, ch->base_addr_c,
1156 &ch->base_addr_y, &ch->base_addr_c);
1157 ch->cache = cache;
1161 for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) {
1162 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k];
1163 sh_mobile_lcdc_overlay_setup(ovl);
1166 /* Start the LCDC. */
1167 __sh_mobile_lcdc_start(priv);
1169 /* Setup deferred I/O, tell the board code to enable the panels, and
1170 * turn backlight on.
1172 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
1173 ch = &priv->ch[k];
1174 if (!ch->enabled)
1175 continue;
1177 tmp = ch->cfg->sys_bus_cfg.deferred_io_msec;
1178 if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
1179 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
1180 ch->defio.delay = msecs_to_jiffies(tmp);
1181 ch->info->fbdefio = &ch->defio;
1182 fb_deferred_io_init(ch->info);
1185 sh_mobile_lcdc_display_on(ch);
1187 if (ch->bl) {
1188 ch->bl->props.power = FB_BLANK_UNBLANK;
1189 backlight_update_status(ch->bl);
1193 return 0;
1196 static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
1198 struct sh_mobile_lcdc_chan *ch;
1199 int k;
1201 /* clean up deferred io and ask board code to disable panel */
1202 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
1203 ch = &priv->ch[k];
1204 if (!ch->enabled)
1205 continue;
1207 /* deferred io mode:
1208 * flush frame, and wait for frame end interrupt
1209 * clean up deferred io and enable clock
1211 if (ch->info && ch->info->fbdefio) {
1212 ch->frame_end = 0;
1213 schedule_delayed_work(&ch->info->deferred_work, 0);
1214 wait_event(ch->frame_end_wait, ch->frame_end);
1215 fb_deferred_io_cleanup(ch->info);
1216 ch->info->fbdefio = NULL;
1217 sh_mobile_lcdc_clk_on(priv);
1220 if (ch->bl) {
1221 ch->bl->props.power = FB_BLANK_POWERDOWN;
1222 backlight_update_status(ch->bl);
1225 sh_mobile_lcdc_display_off(ch);
1227 /* Free the MERAM cache. */
1228 if (ch->cache) {
1229 sh_mobile_meram_cache_free(priv->meram_dev, ch->cache);
1230 ch->cache = NULL;
1235 /* stop the lcdc */
1236 if (priv->started) {
1237 sh_mobile_lcdc_start_stop(priv, 0);
1238 priv->started = 0;
1241 /* stop clocks */
1242 for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
1243 if (priv->ch[k].enabled)
1244 sh_mobile_lcdc_clk_off(priv);
1247 static int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
1248 struct fb_info *info)
1250 if (var->xres > MAX_XRES || var->yres > MAX_YRES)
1251 return -EINVAL;
1253 /* Make sure the virtual resolution is at least as big as the visible
1254 * resolution.
1256 if (var->xres_virtual < var->xres)
1257 var->xres_virtual = var->xres;
1258 if (var->yres_virtual < var->yres)
1259 var->yres_virtual = var->yres;
1261 if (sh_mobile_format_is_fourcc(var)) {
1262 const struct sh_mobile_lcdc_format_info *format;
1264 format = sh_mobile_format_info(var->grayscale);
1265 if (format == NULL)
1266 return -EINVAL;
1267 var->bits_per_pixel = format->bpp;
1269 /* Default to RGB and JPEG color-spaces for RGB and YUV formats
1270 * respectively.
1272 if (!format->yuv)
1273 var->colorspace = V4L2_COLORSPACE_SRGB;
1274 else if (var->colorspace != V4L2_COLORSPACE_REC709)
1275 var->colorspace = V4L2_COLORSPACE_JPEG;
1276 } else {
1277 if (var->bits_per_pixel <= 16) { /* RGB 565 */
1278 var->bits_per_pixel = 16;
1279 var->red.offset = 11;
1280 var->red.length = 5;
1281 var->green.offset = 5;
1282 var->green.length = 6;
1283 var->blue.offset = 0;
1284 var->blue.length = 5;
1285 var->transp.offset = 0;
1286 var->transp.length = 0;
1287 } else if (var->bits_per_pixel <= 24) { /* RGB 888 */
1288 var->bits_per_pixel = 24;
1289 var->red.offset = 16;
1290 var->red.length = 8;
1291 var->green.offset = 8;
1292 var->green.length = 8;
1293 var->blue.offset = 0;
1294 var->blue.length = 8;
1295 var->transp.offset = 0;
1296 var->transp.length = 0;
1297 } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
1298 var->bits_per_pixel = 32;
1299 var->red.offset = 16;
1300 var->red.length = 8;
1301 var->green.offset = 8;
1302 var->green.length = 8;
1303 var->blue.offset = 0;
1304 var->blue.length = 8;
1305 var->transp.offset = 24;
1306 var->transp.length = 8;
1307 } else
1308 return -EINVAL;
1310 var->red.msb_right = 0;
1311 var->green.msb_right = 0;
1312 var->blue.msb_right = 0;
1313 var->transp.msb_right = 0;
1316 /* Make sure we don't exceed our allocated memory. */
1317 if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
1318 info->fix.smem_len)
1319 return -EINVAL;
1321 return 0;
1324 /* -----------------------------------------------------------------------------
1325 * Frame buffer operations - Overlays
1328 static ssize_t
1329 overlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf)
1331 struct fb_info *info = dev_get_drvdata(dev);
1332 struct sh_mobile_lcdc_overlay *ovl = info->par;
1334 return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->alpha);
1337 static ssize_t
1338 overlay_alpha_store(struct device *dev, struct device_attribute *attr,
1339 const char *buf, size_t count)
1341 struct fb_info *info = dev_get_drvdata(dev);
1342 struct sh_mobile_lcdc_overlay *ovl = info->par;
1343 unsigned int alpha;
1344 char *endp;
1346 alpha = simple_strtoul(buf, &endp, 10);
1347 if (isspace(*endp))
1348 endp++;
1350 if (endp - buf != count)
1351 return -EINVAL;
1353 if (alpha > 255)
1354 return -EINVAL;
1356 if (ovl->alpha != alpha) {
1357 ovl->alpha = alpha;
1359 if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled)
1360 sh_mobile_lcdc_overlay_setup(ovl);
1363 return count;
1366 static ssize_t
1367 overlay_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
1369 struct fb_info *info = dev_get_drvdata(dev);
1370 struct sh_mobile_lcdc_overlay *ovl = info->par;
1372 return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->mode);
1375 static ssize_t
1376 overlay_mode_store(struct device *dev, struct device_attribute *attr,
1377 const char *buf, size_t count)
1379 struct fb_info *info = dev_get_drvdata(dev);
1380 struct sh_mobile_lcdc_overlay *ovl = info->par;
1381 unsigned int mode;
1382 char *endp;
1384 mode = simple_strtoul(buf, &endp, 10);
1385 if (isspace(*endp))
1386 endp++;
1388 if (endp - buf != count)
1389 return -EINVAL;
1391 if (mode != LCDC_OVERLAY_BLEND && mode != LCDC_OVERLAY_ROP3)
1392 return -EINVAL;
1394 if (ovl->mode != mode) {
1395 ovl->mode = mode;
1397 if (ovl->enabled)
1398 sh_mobile_lcdc_overlay_setup(ovl);
1401 return count;
1404 static ssize_t
1405 overlay_position_show(struct device *dev, struct device_attribute *attr,
1406 char *buf)
1408 struct fb_info *info = dev_get_drvdata(dev);
1409 struct sh_mobile_lcdc_overlay *ovl = info->par;
1411 return scnprintf(buf, PAGE_SIZE, "%d,%d\n", ovl->pos_x, ovl->pos_y);
1414 static ssize_t
1415 overlay_position_store(struct device *dev, struct device_attribute *attr,
1416 const char *buf, size_t count)
1418 struct fb_info *info = dev_get_drvdata(dev);
1419 struct sh_mobile_lcdc_overlay *ovl = info->par;
1420 char *endp;
1421 int pos_x;
1422 int pos_y;
1424 pos_x = simple_strtol(buf, &endp, 10);
1425 if (*endp != ',')
1426 return -EINVAL;
1428 pos_y = simple_strtol(endp + 1, &endp, 10);
1429 if (isspace(*endp))
1430 endp++;
1432 if (endp - buf != count)
1433 return -EINVAL;
1435 if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) {
1436 ovl->pos_x = pos_x;
1437 ovl->pos_y = pos_y;
1439 if (ovl->enabled)
1440 sh_mobile_lcdc_overlay_setup(ovl);
1443 return count;
1446 static ssize_t
1447 overlay_rop3_show(struct device *dev, struct device_attribute *attr, char *buf)
1449 struct fb_info *info = dev_get_drvdata(dev);
1450 struct sh_mobile_lcdc_overlay *ovl = info->par;
1452 return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->rop3);
1455 static ssize_t
1456 overlay_rop3_store(struct device *dev, struct device_attribute *attr,
1457 const char *buf, size_t count)
1459 struct fb_info *info = dev_get_drvdata(dev);
1460 struct sh_mobile_lcdc_overlay *ovl = info->par;
1461 unsigned int rop3;
1462 char *endp;
1464 rop3 = !!simple_strtoul(buf, &endp, 10);
1465 if (isspace(*endp))
1466 endp++;
1468 if (endp - buf != count)
1469 return -EINVAL;
1471 if (rop3 > 255)
1472 return -EINVAL;
1474 if (ovl->rop3 != rop3) {
1475 ovl->rop3 = rop3;
1477 if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled)
1478 sh_mobile_lcdc_overlay_setup(ovl);
1481 return count;
1484 static const struct device_attribute overlay_sysfs_attrs[] = {
1485 __ATTR(ovl_alpha, S_IRUGO|S_IWUSR,
1486 overlay_alpha_show, overlay_alpha_store),
1487 __ATTR(ovl_mode, S_IRUGO|S_IWUSR,
1488 overlay_mode_show, overlay_mode_store),
1489 __ATTR(ovl_position, S_IRUGO|S_IWUSR,
1490 overlay_position_show, overlay_position_store),
1491 __ATTR(ovl_rop3, S_IRUGO|S_IWUSR,
1492 overlay_rop3_show, overlay_rop3_store),
1495 static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = {
1496 .id = "SH Mobile LCDC",
1497 .type = FB_TYPE_PACKED_PIXELS,
1498 .visual = FB_VISUAL_TRUECOLOR,
1499 .accel = FB_ACCEL_NONE,
1500 .xpanstep = 1,
1501 .ypanstep = 1,
1502 .ywrapstep = 0,
1503 .capabilities = FB_CAP_FOURCC,
1506 static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
1507 struct fb_info *info)
1509 struct sh_mobile_lcdc_overlay *ovl = info->par;
1510 unsigned long base_addr_y;
1511 unsigned long base_addr_c;
1512 unsigned long y_offset;
1513 unsigned long c_offset;
1515 if (!ovl->format->yuv) {
1516 y_offset = (var->yoffset * ovl->xres_virtual + var->xoffset)
1517 * ovl->format->bpp / 8;
1518 c_offset = 0;
1519 } else {
1520 unsigned int xsub = ovl->format->bpp < 24 ? 2 : 1;
1521 unsigned int ysub = ovl->format->bpp < 16 ? 2 : 1;
1523 y_offset = var->yoffset * ovl->xres_virtual + var->xoffset;
1524 c_offset = var->yoffset / ysub * ovl->xres_virtual * 2 / xsub
1525 + var->xoffset * 2 / xsub;
1528 /* If the Y offset hasn't changed, the C offset hasn't either. There's
1529 * nothing to do in that case.
1531 if (y_offset == ovl->pan_y_offset)
1532 return 0;
1534 /* Set the source address for the next refresh */
1535 base_addr_y = ovl->dma_handle + y_offset;
1536 base_addr_c = ovl->dma_handle + ovl->xres_virtual * ovl->yres_virtual
1537 + c_offset;
1539 ovl->base_addr_y = base_addr_y;
1540 ovl->base_addr_c = base_addr_c;
1541 ovl->pan_y_offset = y_offset;
1543 lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
1545 lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
1546 lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
1548 lcdc_write(ovl->channel->lcdc, LDBCR,
1549 LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
1551 return 0;
1554 static int sh_mobile_lcdc_overlay_ioctl(struct fb_info *info, unsigned int cmd,
1555 unsigned long arg)
1557 struct sh_mobile_lcdc_overlay *ovl = info->par;
1559 switch (cmd) {
1560 case FBIO_WAITFORVSYNC:
1561 return sh_mobile_lcdc_wait_for_vsync(ovl->channel);
1563 default:
1564 return -ENOIOCTLCMD;
1568 static int sh_mobile_lcdc_overlay_check_var(struct fb_var_screeninfo *var,
1569 struct fb_info *info)
1571 return __sh_mobile_lcdc_check_var(var, info);
1574 static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info)
1576 struct sh_mobile_lcdc_overlay *ovl = info->par;
1578 ovl->format =
1579 sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
1581 ovl->xres = info->var.xres;
1582 ovl->xres_virtual = info->var.xres_virtual;
1583 ovl->yres = info->var.yres;
1584 ovl->yres_virtual = info->var.yres_virtual;
1586 if (ovl->format->yuv)
1587 ovl->pitch = info->var.xres_virtual;
1588 else
1589 ovl->pitch = info->var.xres_virtual * ovl->format->bpp / 8;
1591 sh_mobile_lcdc_overlay_setup(ovl);
1593 info->fix.line_length = ovl->pitch;
1595 if (sh_mobile_format_is_fourcc(&info->var)) {
1596 info->fix.type = FB_TYPE_FOURCC;
1597 info->fix.visual = FB_VISUAL_FOURCC;
1598 } else {
1599 info->fix.type = FB_TYPE_PACKED_PIXELS;
1600 info->fix.visual = FB_VISUAL_TRUECOLOR;
1603 return 0;
1606 /* Overlay blanking. Disable the overlay when blanked. */
1607 static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info)
1609 struct sh_mobile_lcdc_overlay *ovl = info->par;
1611 ovl->enabled = !blank;
1612 sh_mobile_lcdc_overlay_setup(ovl);
1614 /* Prevent the backlight from receiving a blanking event by returning
1615 * a non-zero value.
1617 return 1;
1620 static int
1621 sh_mobile_lcdc_overlay_mmap(struct fb_info *info, struct vm_area_struct *vma)
1623 struct sh_mobile_lcdc_overlay *ovl = info->par;
1625 return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem,
1626 ovl->dma_handle, ovl->fb_size);
1629 static struct fb_ops sh_mobile_lcdc_overlay_ops = {
1630 .owner = THIS_MODULE,
1631 .fb_read = fb_sys_read,
1632 .fb_write = fb_sys_write,
1633 .fb_fillrect = sys_fillrect,
1634 .fb_copyarea = sys_copyarea,
1635 .fb_imageblit = sys_imageblit,
1636 .fb_blank = sh_mobile_lcdc_overlay_blank,
1637 .fb_pan_display = sh_mobile_lcdc_overlay_pan,
1638 .fb_ioctl = sh_mobile_lcdc_overlay_ioctl,
1639 .fb_check_var = sh_mobile_lcdc_overlay_check_var,
1640 .fb_set_par = sh_mobile_lcdc_overlay_set_par,
1641 .fb_mmap = sh_mobile_lcdc_overlay_mmap,
1644 static void
1645 sh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl)
1647 struct fb_info *info = ovl->info;
1649 if (info == NULL || info->dev == NULL)
1650 return;
1652 unregister_framebuffer(ovl->info);
1655 static int
1656 sh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl)
1658 struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc;
1659 struct fb_info *info = ovl->info;
1660 unsigned int i;
1661 int ret;
1663 if (info == NULL)
1664 return 0;
1666 ret = register_framebuffer(info);
1667 if (ret < 0)
1668 return ret;
1670 dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n",
1671 dev_name(lcdc->dev), ovl->index, info->var.xres,
1672 info->var.yres, info->var.bits_per_pixel);
1674 for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) {
1675 ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]);
1676 if (ret < 0)
1677 return ret;
1680 return 0;
1683 static void
1684 sh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl)
1686 struct fb_info *info = ovl->info;
1688 if (info == NULL || info->device == NULL)
1689 return;
1691 framebuffer_release(info);
1694 static int
1695 sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
1697 struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc;
1698 struct fb_var_screeninfo *var;
1699 struct fb_info *info;
1701 /* Allocate and initialize the frame buffer device. */
1702 info = framebuffer_alloc(0, priv->dev);
1703 if (info == NULL) {
1704 dev_err(priv->dev, "unable to allocate fb_info\n");
1705 return -ENOMEM;
1708 ovl->info = info;
1710 info->flags = FBINFO_FLAG_DEFAULT;
1711 info->fbops = &sh_mobile_lcdc_overlay_ops;
1712 info->device = priv->dev;
1713 info->screen_base = ovl->fb_mem;
1714 info->par = ovl;
1716 /* Initialize fixed screen information. Restrict pan to 2 lines steps
1717 * for NV12 and NV21.
1719 info->fix = sh_mobile_lcdc_overlay_fix;
1720 snprintf(info->fix.id, sizeof(info->fix.id),
1721 "SH Mobile LCDC Overlay %u", ovl->index);
1722 info->fix.smem_start = ovl->dma_handle;
1723 info->fix.smem_len = ovl->fb_size;
1724 info->fix.line_length = ovl->pitch;
1726 if (ovl->format->yuv)
1727 info->fix.visual = FB_VISUAL_FOURCC;
1728 else
1729 info->fix.visual = FB_VISUAL_TRUECOLOR;
1731 switch (ovl->format->fourcc) {
1732 case V4L2_PIX_FMT_NV12:
1733 case V4L2_PIX_FMT_NV21:
1734 info->fix.ypanstep = 2;
1735 case V4L2_PIX_FMT_NV16:
1736 case V4L2_PIX_FMT_NV61:
1737 info->fix.xpanstep = 2;
1740 /* Initialize variable screen information. */
1741 var = &info->var;
1742 memset(var, 0, sizeof(*var));
1743 var->xres = ovl->xres;
1744 var->yres = ovl->yres;
1745 var->xres_virtual = ovl->xres_virtual;
1746 var->yres_virtual = ovl->yres_virtual;
1747 var->activate = FB_ACTIVATE_NOW;
1749 /* Use the legacy API by default for RGB formats, and the FOURCC API
1750 * for YUV formats.
1752 if (!ovl->format->yuv)
1753 var->bits_per_pixel = ovl->format->bpp;
1754 else
1755 var->grayscale = ovl->format->fourcc;
1757 return sh_mobile_lcdc_overlay_check_var(var, info);
1760 /* -----------------------------------------------------------------------------
1761 * Frame buffer operations - main frame buffer
1764 static int sh_mobile_lcdc_setcolreg(u_int regno,
1765 u_int red, u_int green, u_int blue,
1766 u_int transp, struct fb_info *info)
1768 u32 *palette = info->pseudo_palette;
1770 if (regno >= PALETTE_NR)
1771 return -EINVAL;
1773 /* only FB_VISUAL_TRUECOLOR supported */
1775 red >>= 16 - info->var.red.length;
1776 green >>= 16 - info->var.green.length;
1777 blue >>= 16 - info->var.blue.length;
1778 transp >>= 16 - info->var.transp.length;
1780 palette[regno] = (red << info->var.red.offset) |
1781 (green << info->var.green.offset) |
1782 (blue << info->var.blue.offset) |
1783 (transp << info->var.transp.offset);
1785 return 0;
1788 static const struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
1789 .id = "SH Mobile LCDC",
1790 .type = FB_TYPE_PACKED_PIXELS,
1791 .visual = FB_VISUAL_TRUECOLOR,
1792 .accel = FB_ACCEL_NONE,
1793 .xpanstep = 1,
1794 .ypanstep = 1,
1795 .ywrapstep = 0,
1796 .capabilities = FB_CAP_FOURCC,
1799 static void sh_mobile_lcdc_fillrect(struct fb_info *info,
1800 const struct fb_fillrect *rect)
1802 sys_fillrect(info, rect);
1803 sh_mobile_lcdc_deferred_io_touch(info);
1806 static void sh_mobile_lcdc_copyarea(struct fb_info *info,
1807 const struct fb_copyarea *area)
1809 sys_copyarea(info, area);
1810 sh_mobile_lcdc_deferred_io_touch(info);
1813 static void sh_mobile_lcdc_imageblit(struct fb_info *info,
1814 const struct fb_image *image)
1816 sys_imageblit(info, image);
1817 sh_mobile_lcdc_deferred_io_touch(info);
1820 static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
1821 struct fb_info *info)
1823 struct sh_mobile_lcdc_chan *ch = info->par;
1824 struct sh_mobile_lcdc_priv *priv = ch->lcdc;
1825 unsigned long ldrcntr;
1826 unsigned long base_addr_y, base_addr_c;
1827 unsigned long y_offset;
1828 unsigned long c_offset;
1830 if (!ch->format->yuv) {
1831 y_offset = (var->yoffset * ch->xres_virtual + var->xoffset)
1832 * ch->format->bpp / 8;
1833 c_offset = 0;
1834 } else {
1835 unsigned int xsub = ch->format->bpp < 24 ? 2 : 1;
1836 unsigned int ysub = ch->format->bpp < 16 ? 2 : 1;
1838 y_offset = var->yoffset * ch->xres_virtual + var->xoffset;
1839 c_offset = var->yoffset / ysub * ch->xres_virtual * 2 / xsub
1840 + var->xoffset * 2 / xsub;
1843 /* If the Y offset hasn't changed, the C offset hasn't either. There's
1844 * nothing to do in that case.
1846 if (y_offset == ch->pan_y_offset)
1847 return 0;
1849 /* Set the source address for the next refresh */
1850 base_addr_y = ch->dma_handle + y_offset;
1851 base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual
1852 + c_offset;
1854 if (ch->cache)
1855 sh_mobile_meram_cache_update(priv->meram_dev, ch->cache,
1856 base_addr_y, base_addr_c,
1857 &base_addr_y, &base_addr_c);
1859 ch->base_addr_y = base_addr_y;
1860 ch->base_addr_c = base_addr_c;
1861 ch->pan_y_offset = y_offset;
1863 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
1864 if (ch->format->yuv)
1865 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
1867 ldrcntr = lcdc_read(priv, _LDRCNTR);
1868 if (lcdc_chan_is_sublcd(ch))
1869 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
1870 else
1871 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
1874 sh_mobile_lcdc_deferred_io_touch(info);
1876 return 0;
1879 static int sh_mobile_lcdc_ioctl(struct fb_info *info, unsigned int cmd,
1880 unsigned long arg)
1882 struct sh_mobile_lcdc_chan *ch = info->par;
1883 int retval;
1885 switch (cmd) {
1886 case FBIO_WAITFORVSYNC:
1887 retval = sh_mobile_lcdc_wait_for_vsync(ch);
1888 break;
1890 default:
1891 retval = -ENOIOCTLCMD;
1892 break;
1894 return retval;
1897 static void sh_mobile_fb_reconfig(struct fb_info *info)
1899 struct sh_mobile_lcdc_chan *ch = info->par;
1900 struct fb_var_screeninfo var;
1901 struct fb_videomode mode;
1902 struct fb_event event;
1903 int evnt = FB_EVENT_MODE_CHANGE_ALL;
1905 if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par))
1906 /* More framebuffer users are active */
1907 return;
1909 fb_var_to_videomode(&mode, &info->var);
1911 if (fb_mode_is_equal(&ch->display.mode, &mode))
1912 return;
1914 /* Display has been re-plugged, framebuffer is free now, reconfigure */
1915 var = info->var;
1916 fb_videomode_to_var(&var, &ch->display.mode);
1917 var.width = ch->display.width;
1918 var.height = ch->display.height;
1919 var.activate = FB_ACTIVATE_NOW;
1921 if (fb_set_var(info, &var) < 0)
1922 /* Couldn't reconfigure, hopefully, can continue as before */
1923 return;
1926 * fb_set_var() calls the notifier change internally, only if
1927 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
1928 * user event, we have to call the chain ourselves.
1930 event.info = info;
1931 event.data = &ch->display.mode;
1932 fb_notifier_call_chain(evnt, &event);
1936 * Locking: both .fb_release() and .fb_open() are called with info->lock held if
1937 * user == 1, or with console sem held, if user == 0.
1939 static int sh_mobile_lcdc_release(struct fb_info *info, int user)
1941 struct sh_mobile_lcdc_chan *ch = info->par;
1943 mutex_lock(&ch->open_lock);
1944 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
1946 ch->use_count--;
1948 /* Nothing to reconfigure, when called from fbcon */
1949 if (user) {
1950 console_lock();
1951 sh_mobile_fb_reconfig(info);
1952 console_unlock();
1955 mutex_unlock(&ch->open_lock);
1957 return 0;
1960 static int sh_mobile_lcdc_open(struct fb_info *info, int user)
1962 struct sh_mobile_lcdc_chan *ch = info->par;
1964 mutex_lock(&ch->open_lock);
1965 ch->use_count++;
1967 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
1968 mutex_unlock(&ch->open_lock);
1970 return 0;
1973 static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
1974 struct fb_info *info)
1976 struct sh_mobile_lcdc_chan *ch = info->par;
1977 struct sh_mobile_lcdc_priv *p = ch->lcdc;
1978 unsigned int best_dist = (unsigned int)-1;
1979 unsigned int best_xres = 0;
1980 unsigned int best_yres = 0;
1981 unsigned int i;
1982 int ret;
1984 /* If board code provides us with a list of available modes, make sure
1985 * we use one of them. Find the mode closest to the requested one. The
1986 * distance between two modes is defined as the size of the
1987 * non-overlapping parts of the two rectangles.
1989 for (i = 0; i < ch->cfg->num_modes; ++i) {
1990 const struct fb_videomode *mode = &ch->cfg->lcd_modes[i];
1991 unsigned int dist;
1993 /* We can only round up. */
1994 if (var->xres > mode->xres || var->yres > mode->yres)
1995 continue;
1997 dist = var->xres * var->yres + mode->xres * mode->yres
1998 - 2 * min(var->xres, mode->xres)
1999 * min(var->yres, mode->yres);
2001 if (dist < best_dist) {
2002 best_xres = mode->xres;
2003 best_yres = mode->yres;
2004 best_dist = dist;
2008 /* If no available mode can be used, return an error. */
2009 if (ch->cfg->num_modes != 0) {
2010 if (best_dist == (unsigned int)-1)
2011 return -EINVAL;
2013 var->xres = best_xres;
2014 var->yres = best_yres;
2017 ret = __sh_mobile_lcdc_check_var(var, info);
2018 if (ret < 0)
2019 return ret;
2021 /* only accept the forced_fourcc for dual channel configurations */
2022 if (p->forced_fourcc &&
2023 p->forced_fourcc != sh_mobile_format_fourcc(var))
2024 return -EINVAL;
2026 return 0;
2029 static int sh_mobile_lcdc_set_par(struct fb_info *info)
2031 struct sh_mobile_lcdc_chan *ch = info->par;
2032 int ret;
2034 sh_mobile_lcdc_stop(ch->lcdc);
2036 ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
2037 ch->colorspace = info->var.colorspace;
2039 ch->xres = info->var.xres;
2040 ch->xres_virtual = info->var.xres_virtual;
2041 ch->yres = info->var.yres;
2042 ch->yres_virtual = info->var.yres_virtual;
2044 if (ch->format->yuv)
2045 ch->pitch = info->var.xres_virtual;
2046 else
2047 ch->pitch = info->var.xres_virtual * ch->format->bpp / 8;
2049 ret = sh_mobile_lcdc_start(ch->lcdc);
2050 if (ret < 0)
2051 dev_err(info->dev, "%s: unable to restart LCDC\n", __func__);
2053 info->fix.line_length = ch->pitch;
2055 if (sh_mobile_format_is_fourcc(&info->var)) {
2056 info->fix.type = FB_TYPE_FOURCC;
2057 info->fix.visual = FB_VISUAL_FOURCC;
2058 } else {
2059 info->fix.type = FB_TYPE_PACKED_PIXELS;
2060 info->fix.visual = FB_VISUAL_TRUECOLOR;
2063 return ret;
2067 * Screen blanking. Behavior is as follows:
2068 * FB_BLANK_UNBLANK: screen unblanked, clocks enabled
2069 * FB_BLANK_NORMAL: screen blanked, clocks enabled
2070 * FB_BLANK_VSYNC,
2071 * FB_BLANK_HSYNC,
2072 * FB_BLANK_POWEROFF: screen blanked, clocks disabled
2074 static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
2076 struct sh_mobile_lcdc_chan *ch = info->par;
2077 struct sh_mobile_lcdc_priv *p = ch->lcdc;
2079 /* blank the screen? */
2080 if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
2081 struct fb_fillrect rect = {
2082 .width = ch->xres,
2083 .height = ch->yres,
2085 sh_mobile_lcdc_fillrect(info, &rect);
2087 /* turn clocks on? */
2088 if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) {
2089 sh_mobile_lcdc_clk_on(p);
2091 /* turn clocks off? */
2092 if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) {
2093 /* make sure the screen is updated with the black fill before
2094 * switching the clocks off. one vsync is not enough since
2095 * blanking may occur in the middle of a refresh. deferred io
2096 * mode will reenable the clocks and update the screen in time,
2097 * so it does not need this. */
2098 if (!info->fbdefio) {
2099 sh_mobile_lcdc_wait_for_vsync(ch);
2100 sh_mobile_lcdc_wait_for_vsync(ch);
2102 sh_mobile_lcdc_clk_off(p);
2105 ch->blank_status = blank;
2106 return 0;
2109 static int
2110 sh_mobile_lcdc_mmap(struct fb_info *info, struct vm_area_struct *vma)
2112 struct sh_mobile_lcdc_chan *ch = info->par;
2114 return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem,
2115 ch->dma_handle, ch->fb_size);
2118 static struct fb_ops sh_mobile_lcdc_ops = {
2119 .owner = THIS_MODULE,
2120 .fb_setcolreg = sh_mobile_lcdc_setcolreg,
2121 .fb_read = fb_sys_read,
2122 .fb_write = fb_sys_write,
2123 .fb_fillrect = sh_mobile_lcdc_fillrect,
2124 .fb_copyarea = sh_mobile_lcdc_copyarea,
2125 .fb_imageblit = sh_mobile_lcdc_imageblit,
2126 .fb_blank = sh_mobile_lcdc_blank,
2127 .fb_pan_display = sh_mobile_lcdc_pan,
2128 .fb_ioctl = sh_mobile_lcdc_ioctl,
2129 .fb_open = sh_mobile_lcdc_open,
2130 .fb_release = sh_mobile_lcdc_release,
2131 .fb_check_var = sh_mobile_lcdc_check_var,
2132 .fb_set_par = sh_mobile_lcdc_set_par,
2133 .fb_mmap = sh_mobile_lcdc_mmap,
2136 static void
2137 sh_mobile_lcdc_channel_fb_unregister(struct sh_mobile_lcdc_chan *ch)
2139 if (ch->info && ch->info->dev)
2140 unregister_framebuffer(ch->info);
2143 static int
2144 sh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch)
2146 struct fb_info *info = ch->info;
2147 int ret;
2149 if (info->fbdefio) {
2150 ch->sglist = vmalloc(sizeof(struct scatterlist) *
2151 ch->fb_size >> PAGE_SHIFT);
2152 if (!ch->sglist) {
2153 dev_err(ch->lcdc->dev, "cannot allocate sglist\n");
2154 return -ENOMEM;
2158 info->bl_dev = ch->bl;
2160 ret = register_framebuffer(info);
2161 if (ret < 0)
2162 return ret;
2164 dev_info(ch->lcdc->dev, "registered %s/%s as %dx%d %dbpp.\n",
2165 dev_name(ch->lcdc->dev), (ch->cfg->chan == LCDC_CHAN_MAINLCD) ?
2166 "mainlcd" : "sublcd", info->var.xres, info->var.yres,
2167 info->var.bits_per_pixel);
2169 /* deferred io mode: disable clock to save power */
2170 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
2171 sh_mobile_lcdc_clk_off(ch->lcdc);
2173 return ret;
2176 static void
2177 sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
2179 struct fb_info *info = ch->info;
2181 if (!info || !info->device)
2182 return;
2184 if (ch->sglist)
2185 vfree(ch->sglist);
2187 fb_dealloc_cmap(&info->cmap);
2188 framebuffer_release(info);
2191 static int
2192 sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
2193 const struct fb_videomode *modes,
2194 unsigned int num_modes)
2196 struct sh_mobile_lcdc_priv *priv = ch->lcdc;
2197 struct fb_var_screeninfo *var;
2198 struct fb_info *info;
2199 int ret;
2201 /* Allocate and initialize the frame buffer device. Create the modes
2202 * list and allocate the color map.
2204 info = framebuffer_alloc(0, priv->dev);
2205 if (info == NULL) {
2206 dev_err(priv->dev, "unable to allocate fb_info\n");
2207 return -ENOMEM;
2210 ch->info = info;
2212 info->flags = FBINFO_FLAG_DEFAULT;
2213 info->fbops = &sh_mobile_lcdc_ops;
2214 info->device = priv->dev;
2215 info->screen_base = ch->fb_mem;
2216 info->pseudo_palette = &ch->pseudo_palette;
2217 info->par = ch;
2219 fb_videomode_to_modelist(modes, num_modes, &info->modelist);
2221 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
2222 if (ret < 0) {
2223 dev_err(priv->dev, "unable to allocate cmap\n");
2224 return ret;
2227 /* Initialize fixed screen information. Restrict pan to 2 lines steps
2228 * for NV12 and NV21.
2230 info->fix = sh_mobile_lcdc_fix;
2231 info->fix.smem_start = ch->dma_handle;
2232 info->fix.smem_len = ch->fb_size;
2233 info->fix.line_length = ch->pitch;
2235 if (ch->format->yuv)
2236 info->fix.visual = FB_VISUAL_FOURCC;
2237 else
2238 info->fix.visual = FB_VISUAL_TRUECOLOR;
2240 switch (ch->format->fourcc) {
2241 case V4L2_PIX_FMT_NV12:
2242 case V4L2_PIX_FMT_NV21:
2243 info->fix.ypanstep = 2;
2244 case V4L2_PIX_FMT_NV16:
2245 case V4L2_PIX_FMT_NV61:
2246 info->fix.xpanstep = 2;
2249 /* Initialize variable screen information using the first mode as
2250 * default.
2252 var = &info->var;
2253 fb_videomode_to_var(var, modes);
2254 var->width = ch->display.width;
2255 var->height = ch->display.height;
2256 var->xres_virtual = ch->xres_virtual;
2257 var->yres_virtual = ch->yres_virtual;
2258 var->activate = FB_ACTIVATE_NOW;
2260 /* Use the legacy API by default for RGB formats, and the FOURCC API
2261 * for YUV formats.
2263 if (!ch->format->yuv)
2264 var->bits_per_pixel = ch->format->bpp;
2265 else
2266 var->grayscale = ch->format->fourcc;
2268 ret = sh_mobile_lcdc_check_var(var, info);
2269 if (ret)
2270 return ret;
2272 return 0;
2275 /* -----------------------------------------------------------------------------
2276 * Backlight
2279 static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
2281 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
2282 int brightness = bdev->props.brightness;
2284 if (bdev->props.power != FB_BLANK_UNBLANK ||
2285 bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
2286 brightness = 0;
2288 ch->bl_brightness = brightness;
2289 return ch->cfg->bl_info.set_brightness(brightness);
2292 static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
2294 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
2296 return ch->bl_brightness;
2299 static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
2300 struct fb_info *info)
2302 return (info->bl_dev == bdev);
2305 static struct backlight_ops sh_mobile_lcdc_bl_ops = {
2306 .options = BL_CORE_SUSPENDRESUME,
2307 .update_status = sh_mobile_lcdc_update_bl,
2308 .get_brightness = sh_mobile_lcdc_get_brightness,
2309 .check_fb = sh_mobile_lcdc_check_fb,
2312 static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent,
2313 struct sh_mobile_lcdc_chan *ch)
2315 struct backlight_device *bl;
2317 bl = backlight_device_register(ch->cfg->bl_info.name, parent, ch,
2318 &sh_mobile_lcdc_bl_ops, NULL);
2319 if (IS_ERR(bl)) {
2320 dev_err(parent, "unable to register backlight device: %ld\n",
2321 PTR_ERR(bl));
2322 return NULL;
2325 bl->props.max_brightness = ch->cfg->bl_info.max_brightness;
2326 bl->props.brightness = bl->props.max_brightness;
2327 backlight_update_status(bl);
2329 return bl;
2332 static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
2334 backlight_device_unregister(bdev);
2337 /* -----------------------------------------------------------------------------
2338 * Power management
2341 static int sh_mobile_lcdc_suspend(struct device *dev)
2343 struct platform_device *pdev = to_platform_device(dev);
2345 sh_mobile_lcdc_stop(platform_get_drvdata(pdev));
2346 return 0;
2349 static int sh_mobile_lcdc_resume(struct device *dev)
2351 struct platform_device *pdev = to_platform_device(dev);
2353 return sh_mobile_lcdc_start(platform_get_drvdata(pdev));
2356 static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
2358 struct platform_device *pdev = to_platform_device(dev);
2359 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
2361 /* turn off LCDC hardware */
2362 lcdc_write(priv, _LDCNT1R, 0);
2364 return 0;
2367 static int sh_mobile_lcdc_runtime_resume(struct device *dev)
2369 struct platform_device *pdev = to_platform_device(dev);
2370 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
2372 __sh_mobile_lcdc_start(priv);
2374 return 0;
2377 static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
2378 .suspend = sh_mobile_lcdc_suspend,
2379 .resume = sh_mobile_lcdc_resume,
2380 .runtime_suspend = sh_mobile_lcdc_runtime_suspend,
2381 .runtime_resume = sh_mobile_lcdc_runtime_resume,
2384 /* -----------------------------------------------------------------------------
2385 * Framebuffer notifier
2388 /* locking: called with info->lock held */
2389 static int sh_mobile_lcdc_notify(struct notifier_block *nb,
2390 unsigned long action, void *data)
2392 struct fb_event *event = data;
2393 struct fb_info *info = event->info;
2394 struct sh_mobile_lcdc_chan *ch = info->par;
2396 if (&ch->lcdc->notifier != nb)
2397 return NOTIFY_DONE;
2399 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
2400 __func__, action, event->data);
2402 switch(action) {
2403 case FB_EVENT_SUSPEND:
2404 sh_mobile_lcdc_display_off(ch);
2405 sh_mobile_lcdc_stop(ch->lcdc);
2406 break;
2407 case FB_EVENT_RESUME:
2408 mutex_lock(&ch->open_lock);
2409 sh_mobile_fb_reconfig(info);
2410 mutex_unlock(&ch->open_lock);
2412 sh_mobile_lcdc_display_on(ch);
2413 sh_mobile_lcdc_start(ch->lcdc);
2416 return NOTIFY_OK;
2419 /* -----------------------------------------------------------------------------
2420 * Probe/remove and driver init/exit
2423 static const struct fb_videomode default_720p = {
2424 .name = "HDMI 720p",
2425 .xres = 1280,
2426 .yres = 720,
2428 .left_margin = 220,
2429 .right_margin = 110,
2430 .hsync_len = 40,
2432 .upper_margin = 20,
2433 .lower_margin = 5,
2434 .vsync_len = 5,
2436 .pixclock = 13468,
2437 .refresh = 60,
2438 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
2441 static int sh_mobile_lcdc_remove(struct platform_device *pdev)
2443 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
2444 unsigned int i;
2446 fb_unregister_client(&priv->notifier);
2448 for (i = 0; i < ARRAY_SIZE(priv->overlays); i++)
2449 sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]);
2450 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
2451 sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]);
2453 sh_mobile_lcdc_stop(priv);
2455 for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) {
2456 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
2458 sh_mobile_lcdc_overlay_fb_cleanup(ovl);
2460 if (ovl->fb_mem)
2461 dma_free_coherent(&pdev->dev, ovl->fb_size,
2462 ovl->fb_mem, ovl->dma_handle);
2465 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
2466 struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
2468 if (ch->tx_dev) {
2469 ch->tx_dev->lcdc = NULL;
2470 module_put(ch->cfg->tx_dev->dev.driver->owner);
2473 sh_mobile_lcdc_channel_fb_cleanup(ch);
2475 if (ch->fb_mem)
2476 dma_free_coherent(&pdev->dev, ch->fb_size,
2477 ch->fb_mem, ch->dma_handle);
2480 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
2481 struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
2483 if (ch->bl)
2484 sh_mobile_lcdc_bl_remove(ch->bl);
2485 mutex_destroy(&ch->open_lock);
2488 if (priv->dot_clk) {
2489 pm_runtime_disable(&pdev->dev);
2490 clk_put(priv->dot_clk);
2493 if (priv->base)
2494 iounmap(priv->base);
2496 if (priv->irq)
2497 free_irq(priv->irq, priv);
2498 kfree(priv);
2499 return 0;
2502 static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
2504 int interface_type = ch->cfg->interface_type;
2506 switch (interface_type) {
2507 case RGB8:
2508 case RGB9:
2509 case RGB12A:
2510 case RGB12B:
2511 case RGB16:
2512 case RGB18:
2513 case RGB24:
2514 case SYS8A:
2515 case SYS8B:
2516 case SYS8C:
2517 case SYS8D:
2518 case SYS9:
2519 case SYS12:
2520 case SYS16A:
2521 case SYS16B:
2522 case SYS16C:
2523 case SYS18:
2524 case SYS24:
2525 break;
2526 default:
2527 return -EINVAL;
2530 /* SUBLCD only supports SYS interface */
2531 if (lcdc_chan_is_sublcd(ch)) {
2532 if (!(interface_type & LDMT1R_IFM))
2533 return -EINVAL;
2535 interface_type &= ~LDMT1R_IFM;
2538 ch->ldmt1r_value = interface_type;
2539 return 0;
2542 static int
2543 sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl)
2545 const struct sh_mobile_lcdc_format_info *format;
2546 struct device *dev = ovl->channel->lcdc->dev;
2547 int ret;
2549 if (ovl->cfg->fourcc == 0)
2550 return 0;
2552 /* Validate the format. */
2553 format = sh_mobile_format_info(ovl->cfg->fourcc);
2554 if (format == NULL) {
2555 dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
2556 return -EINVAL;
2559 ovl->enabled = false;
2560 ovl->mode = LCDC_OVERLAY_BLEND;
2561 ovl->alpha = 255;
2562 ovl->rop3 = 0;
2563 ovl->pos_x = 0;
2564 ovl->pos_y = 0;
2566 /* The default Y virtual resolution is twice the panel size to allow for
2567 * double-buffering.
2569 ovl->format = format;
2570 ovl->xres = ovl->cfg->max_xres;
2571 ovl->xres_virtual = ovl->xres;
2572 ovl->yres = ovl->cfg->max_yres;
2573 ovl->yres_virtual = ovl->yres * 2;
2575 if (!format->yuv)
2576 ovl->pitch = ovl->xres_virtual * format->bpp / 8;
2577 else
2578 ovl->pitch = ovl->xres_virtual;
2580 /* Allocate frame buffer memory. */
2581 ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
2582 * format->bpp / 8 * 2;
2583 ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle,
2584 GFP_KERNEL);
2585 if (!ovl->fb_mem) {
2586 dev_err(dev, "unable to allocate buffer\n");
2587 return -ENOMEM;
2590 ret = sh_mobile_lcdc_overlay_fb_init(ovl);
2591 if (ret < 0)
2592 return ret;
2594 return 0;
2597 static int
2598 sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch)
2600 const struct sh_mobile_lcdc_format_info *format;
2601 const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg;
2602 struct device *dev = ch->lcdc->dev;
2603 const struct fb_videomode *max_mode;
2604 const struct fb_videomode *mode;
2605 unsigned int num_modes;
2606 unsigned int max_size;
2607 unsigned int i;
2609 mutex_init(&ch->open_lock);
2610 ch->notify = sh_mobile_lcdc_display_notify;
2612 /* Validate the format. */
2613 format = sh_mobile_format_info(cfg->fourcc);
2614 if (format == NULL) {
2615 dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
2616 return -EINVAL;
2619 /* Iterate through the modes to validate them and find the highest
2620 * resolution.
2622 max_mode = NULL;
2623 max_size = 0;
2625 for (i = 0, mode = cfg->lcd_modes; i < cfg->num_modes; i++, mode++) {
2626 unsigned int size = mode->yres * mode->xres;
2628 /* NV12/NV21 buffers must have even number of lines */
2629 if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
2630 cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
2631 dev_err(dev, "yres must be multiple of 2 for "
2632 "YCbCr420 mode.\n");
2633 return -EINVAL;
2636 if (size > max_size) {
2637 max_mode = mode;
2638 max_size = size;
2642 if (!max_size)
2643 max_size = MAX_XRES * MAX_YRES;
2644 else
2645 dev_dbg(dev, "Found largest videomode %ux%u\n",
2646 max_mode->xres, max_mode->yres);
2648 if (cfg->lcd_modes == NULL) {
2649 mode = &default_720p;
2650 num_modes = 1;
2651 } else {
2652 mode = cfg->lcd_modes;
2653 num_modes = cfg->num_modes;
2656 /* Use the first mode as default. The default Y virtual resolution is
2657 * twice the panel size to allow for double-buffering.
2659 ch->format = format;
2660 ch->xres = mode->xres;
2661 ch->xres_virtual = mode->xres;
2662 ch->yres = mode->yres;
2663 ch->yres_virtual = mode->yres * 2;
2665 if (!format->yuv) {
2666 ch->colorspace = V4L2_COLORSPACE_SRGB;
2667 ch->pitch = ch->xres_virtual * format->bpp / 8;
2668 } else {
2669 ch->colorspace = V4L2_COLORSPACE_REC709;
2670 ch->pitch = ch->xres_virtual;
2673 ch->display.width = cfg->panel_cfg.width;
2674 ch->display.height = cfg->panel_cfg.height;
2675 ch->display.mode = *mode;
2677 /* Allocate frame buffer memory. */
2678 ch->fb_size = max_size * format->bpp / 8 * 2;
2679 ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle,
2680 GFP_KERNEL);
2681 if (ch->fb_mem == NULL) {
2682 dev_err(dev, "unable to allocate buffer\n");
2683 return -ENOMEM;
2686 /* Initialize the transmitter device if present. */
2687 if (cfg->tx_dev) {
2688 if (!cfg->tx_dev->dev.driver ||
2689 !try_module_get(cfg->tx_dev->dev.driver->owner)) {
2690 dev_warn(dev, "unable to get transmitter device\n");
2691 return -EINVAL;
2693 ch->tx_dev = platform_get_drvdata(cfg->tx_dev);
2694 ch->tx_dev->lcdc = ch;
2695 ch->tx_dev->def_mode = *mode;
2698 return sh_mobile_lcdc_channel_fb_init(ch, mode, num_modes);
2701 static int sh_mobile_lcdc_probe(struct platform_device *pdev)
2703 struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
2704 struct sh_mobile_lcdc_priv *priv;
2705 struct resource *res;
2706 int num_channels;
2707 int error;
2708 int i;
2710 if (!pdata) {
2711 dev_err(&pdev->dev, "no platform data defined\n");
2712 return -EINVAL;
2715 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2716 i = platform_get_irq(pdev, 0);
2717 if (!res || i < 0) {
2718 dev_err(&pdev->dev, "cannot get platform resources\n");
2719 return -ENOENT;
2722 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
2723 if (!priv) {
2724 dev_err(&pdev->dev, "cannot allocate device data\n");
2725 return -ENOMEM;
2728 priv->dev = &pdev->dev;
2729 priv->meram_dev = pdata->meram_dev;
2730 platform_set_drvdata(pdev, priv);
2732 error = request_irq(i, sh_mobile_lcdc_irq, 0,
2733 dev_name(&pdev->dev), priv);
2734 if (error) {
2735 dev_err(&pdev->dev, "unable to request irq\n");
2736 goto err1;
2739 priv->irq = i;
2740 atomic_set(&priv->hw_usecnt, -1);
2742 for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) {
2743 struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels;
2745 ch->lcdc = priv;
2746 ch->cfg = &pdata->ch[i];
2748 error = sh_mobile_lcdc_check_interface(ch);
2749 if (error) {
2750 dev_err(&pdev->dev, "unsupported interface type\n");
2751 goto err1;
2753 init_waitqueue_head(&ch->frame_end_wait);
2754 init_completion(&ch->vsync_completion);
2756 /* probe the backlight is there is one defined */
2757 if (ch->cfg->bl_info.max_brightness)
2758 ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch);
2760 switch (pdata->ch[i].chan) {
2761 case LCDC_CHAN_MAINLCD:
2762 ch->enabled = LDCNT2R_ME;
2763 ch->reg_offs = lcdc_offs_mainlcd;
2764 num_channels++;
2765 break;
2766 case LCDC_CHAN_SUBLCD:
2767 ch->enabled = LDCNT2R_SE;
2768 ch->reg_offs = lcdc_offs_sublcd;
2769 num_channels++;
2770 break;
2774 if (!num_channels) {
2775 dev_err(&pdev->dev, "no channels defined\n");
2776 error = -EINVAL;
2777 goto err1;
2780 /* for dual channel LCDC (MAIN + SUB) force shared format setting */
2781 if (num_channels == 2)
2782 priv->forced_fourcc = pdata->ch[0].fourcc;
2784 priv->base = ioremap_nocache(res->start, resource_size(res));
2785 if (!priv->base)
2786 goto err1;
2788 error = sh_mobile_lcdc_setup_clocks(priv, pdata->clock_source);
2789 if (error) {
2790 dev_err(&pdev->dev, "unable to setup clocks\n");
2791 goto err1;
2794 /* Enable runtime PM. */
2795 pm_runtime_enable(&pdev->dev);
2797 for (i = 0; i < num_channels; i++) {
2798 struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
2800 error = sh_mobile_lcdc_channel_init(ch);
2801 if (error)
2802 goto err1;
2805 for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
2806 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
2808 ovl->cfg = &pdata->overlays[i];
2809 ovl->channel = &priv->ch[0];
2811 error = sh_mobile_lcdc_overlay_init(ovl);
2812 if (error)
2813 goto err1;
2816 error = sh_mobile_lcdc_start(priv);
2817 if (error) {
2818 dev_err(&pdev->dev, "unable to start hardware\n");
2819 goto err1;
2822 for (i = 0; i < num_channels; i++) {
2823 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
2825 error = sh_mobile_lcdc_channel_fb_register(ch);
2826 if (error)
2827 goto err1;
2830 for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
2831 struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
2833 error = sh_mobile_lcdc_overlay_fb_register(ovl);
2834 if (error)
2835 goto err1;
2838 /* Failure ignored */
2839 priv->notifier.notifier_call = sh_mobile_lcdc_notify;
2840 fb_register_client(&priv->notifier);
2842 return 0;
2843 err1:
2844 sh_mobile_lcdc_remove(pdev);
2846 return error;
2849 static struct platform_driver sh_mobile_lcdc_driver = {
2850 .driver = {
2851 .name = "sh_mobile_lcdc_fb",
2852 .owner = THIS_MODULE,
2853 .pm = &sh_mobile_lcdc_dev_pm_ops,
2855 .probe = sh_mobile_lcdc_probe,
2856 .remove = sh_mobile_lcdc_remove,
2859 module_platform_driver(sh_mobile_lcdc_driver);
2861 MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
2862 MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
2863 MODULE_LICENSE("GPL v2");