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
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/delay.h>
15 #include <linux/clk.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/platform_device.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/interrupt.h>
20 #include <linux/videodev2.h>
21 #include <linux/vmalloc.h>
22 #include <linux/ioctl.h>
23 #include <linux/slab.h>
24 #include <linux/console.h>
25 #include <linux/backlight.h>
26 #include <linux/gpio.h>
27 #include <linux/module.h>
28 #include <video/sh_mobile_lcdc.h>
29 #include <video/sh_mobile_meram.h>
30 #include <linux/atomic.h>
32 #include "sh_mobile_lcdcfb.h"
34 #define SIDE_B_OFFSET 0x1000
35 #define MIRROR_OFFSET 0x2000
40 static unsigned long lcdc_offs_mainlcd
[NR_CH_REGS
] = {
60 static unsigned long lcdc_offs_sublcd
[NR_CH_REGS
] = {
78 static const struct fb_videomode default_720p
= {
93 .sync
= FB_SYNC_VERT_HIGH_ACT
| FB_SYNC_HOR_HIGH_ACT
,
96 struct sh_mobile_lcdc_priv
{
102 unsigned long lddckr
;
103 struct sh_mobile_lcdc_chan ch
[2];
104 struct notifier_block notifier
;
106 int forced_fourcc
; /* 2 channel LCDC must share fourcc setting */
107 struct sh_mobile_meram_info
*meram_dev
;
110 static bool banked(int reg_nr
)
130 static void lcdc_write_chan(struct sh_mobile_lcdc_chan
*chan
,
131 int reg_nr
, unsigned long data
)
133 iowrite32(data
, chan
->lcdc
->base
+ chan
->reg_offs
[reg_nr
]);
135 iowrite32(data
, chan
->lcdc
->base
+ chan
->reg_offs
[reg_nr
] +
139 static void lcdc_write_chan_mirror(struct sh_mobile_lcdc_chan
*chan
,
140 int reg_nr
, unsigned long data
)
142 iowrite32(data
, chan
->lcdc
->base
+ chan
->reg_offs
[reg_nr
] +
146 static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan
*chan
,
149 return ioread32(chan
->lcdc
->base
+ chan
->reg_offs
[reg_nr
]);
152 static void lcdc_write(struct sh_mobile_lcdc_priv
*priv
,
153 unsigned long reg_offs
, unsigned long data
)
155 iowrite32(data
, priv
->base
+ reg_offs
);
158 static unsigned long lcdc_read(struct sh_mobile_lcdc_priv
*priv
,
159 unsigned long reg_offs
)
161 return ioread32(priv
->base
+ reg_offs
);
164 static void lcdc_wait_bit(struct sh_mobile_lcdc_priv
*priv
,
165 unsigned long reg_offs
,
166 unsigned long mask
, unsigned long until
)
168 while ((lcdc_read(priv
, reg_offs
) & mask
) != until
)
172 static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan
*chan
)
174 return chan
->cfg
.chan
== LCDC_CHAN_SUBLCD
;
177 static void lcdc_sys_write_index(void *handle
, unsigned long data
)
179 struct sh_mobile_lcdc_chan
*ch
= handle
;
181 lcdc_write(ch
->lcdc
, _LDDWD0R
, data
| LDDWDxR_WDACT
);
182 lcdc_wait_bit(ch
->lcdc
, _LDSR
, LDSR_AS
, 0);
183 lcdc_write(ch
->lcdc
, _LDDWAR
, LDDWAR_WA
|
184 (lcdc_chan_is_sublcd(ch
) ? 2 : 0));
185 lcdc_wait_bit(ch
->lcdc
, _LDSR
, LDSR_AS
, 0);
188 static void lcdc_sys_write_data(void *handle
, unsigned long data
)
190 struct sh_mobile_lcdc_chan
*ch
= handle
;
192 lcdc_write(ch
->lcdc
, _LDDWD0R
, data
| LDDWDxR_WDACT
| LDDWDxR_RSW
);
193 lcdc_wait_bit(ch
->lcdc
, _LDSR
, LDSR_AS
, 0);
194 lcdc_write(ch
->lcdc
, _LDDWAR
, LDDWAR_WA
|
195 (lcdc_chan_is_sublcd(ch
) ? 2 : 0));
196 lcdc_wait_bit(ch
->lcdc
, _LDSR
, LDSR_AS
, 0);
199 static unsigned long lcdc_sys_read_data(void *handle
)
201 struct sh_mobile_lcdc_chan
*ch
= handle
;
203 lcdc_write(ch
->lcdc
, _LDDRDR
, LDDRDR_RSR
);
204 lcdc_wait_bit(ch
->lcdc
, _LDSR
, LDSR_AS
, 0);
205 lcdc_write(ch
->lcdc
, _LDDRAR
, LDDRAR_RA
|
206 (lcdc_chan_is_sublcd(ch
) ? 2 : 0));
208 lcdc_wait_bit(ch
->lcdc
, _LDSR
, LDSR_AS
, 0);
210 return lcdc_read(ch
->lcdc
, _LDDRDR
) & LDDRDR_DRD_MASK
;
213 struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops
= {
214 lcdc_sys_write_index
,
219 static int sh_mobile_format_fourcc(const struct fb_var_screeninfo
*var
)
221 if (var
->grayscale
> 1)
222 return var
->grayscale
;
224 switch (var
->bits_per_pixel
) {
226 return V4L2_PIX_FMT_RGB565
;
228 return V4L2_PIX_FMT_BGR24
;
230 return V4L2_PIX_FMT_BGR32
;
236 static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo
*var
)
238 return var
->grayscale
> 1;
241 static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo
*var
)
243 if (var
->grayscale
<= 1)
246 switch (var
->grayscale
) {
247 case V4L2_PIX_FMT_NV12
:
248 case V4L2_PIX_FMT_NV21
:
249 case V4L2_PIX_FMT_NV16
:
250 case V4L2_PIX_FMT_NV61
:
251 case V4L2_PIX_FMT_NV24
:
252 case V4L2_PIX_FMT_NV42
:
260 static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv
*priv
)
262 if (atomic_inc_and_test(&priv
->hw_usecnt
)) {
264 clk_enable(priv
->dot_clk
);
265 pm_runtime_get_sync(priv
->dev
);
266 if (priv
->meram_dev
&& priv
->meram_dev
->pdev
)
267 pm_runtime_get_sync(&priv
->meram_dev
->pdev
->dev
);
271 static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv
*priv
)
273 if (atomic_sub_return(1, &priv
->hw_usecnt
) == -1) {
274 if (priv
->meram_dev
&& priv
->meram_dev
->pdev
)
275 pm_runtime_put_sync(&priv
->meram_dev
->pdev
->dev
);
276 pm_runtime_put(priv
->dev
);
278 clk_disable(priv
->dot_clk
);
282 static int sh_mobile_lcdc_sginit(struct fb_info
*info
,
283 struct list_head
*pagelist
)
285 struct sh_mobile_lcdc_chan
*ch
= info
->par
;
286 unsigned int nr_pages_max
= info
->fix
.smem_len
>> PAGE_SHIFT
;
290 sg_init_table(ch
->sglist
, nr_pages_max
);
292 list_for_each_entry(page
, pagelist
, lru
)
293 sg_set_page(&ch
->sglist
[nr_pages
++], page
, PAGE_SIZE
, 0);
298 static void sh_mobile_lcdc_deferred_io(struct fb_info
*info
,
299 struct list_head
*pagelist
)
301 struct sh_mobile_lcdc_chan
*ch
= info
->par
;
302 struct sh_mobile_lcdc_board_cfg
*bcfg
= &ch
->cfg
.board_cfg
;
304 /* enable clocks before accessing hardware */
305 sh_mobile_lcdc_clk_on(ch
->lcdc
);
308 * It's possible to get here without anything on the pagelist via
309 * sh_mobile_lcdc_deferred_io_touch() or via a userspace fsync()
310 * invocation. In the former case, the acceleration routines are
311 * stepped in to when using the framebuffer console causing the
312 * workqueue to be scheduled without any dirty pages on the list.
314 * Despite this, a panel update is still needed given that the
315 * acceleration routines have their own methods for writing in
316 * that still need to be updated.
318 * The fsync() and empty pagelist case could be optimized for,
319 * but we don't bother, as any application exhibiting such
320 * behaviour is fundamentally broken anyways.
322 if (!list_empty(pagelist
)) {
323 unsigned int nr_pages
= sh_mobile_lcdc_sginit(info
, pagelist
);
325 /* trigger panel update */
326 dma_map_sg(info
->dev
, ch
->sglist
, nr_pages
, DMA_TO_DEVICE
);
327 if (bcfg
->start_transfer
)
328 bcfg
->start_transfer(bcfg
->board_data
, ch
,
329 &sh_mobile_lcdc_sys_bus_ops
);
330 lcdc_write_chan(ch
, LDSM2R
, LDSM2R_OSTRG
);
331 dma_unmap_sg(info
->dev
, ch
->sglist
, nr_pages
, DMA_TO_DEVICE
);
333 if (bcfg
->start_transfer
)
334 bcfg
->start_transfer(bcfg
->board_data
, ch
,
335 &sh_mobile_lcdc_sys_bus_ops
);
336 lcdc_write_chan(ch
, LDSM2R
, LDSM2R_OSTRG
);
340 static void sh_mobile_lcdc_deferred_io_touch(struct fb_info
*info
)
342 struct fb_deferred_io
*fbdefio
= info
->fbdefio
;
345 schedule_delayed_work(&info
->deferred_work
, fbdefio
->delay
);
348 static irqreturn_t
sh_mobile_lcdc_irq(int irq
, void *data
)
350 struct sh_mobile_lcdc_priv
*priv
= data
;
351 struct sh_mobile_lcdc_chan
*ch
;
352 unsigned long ldintr
;
356 /* Acknowledge interrupts and disable further VSYNC End IRQs. */
357 ldintr
= lcdc_read(priv
, _LDINTR
);
358 lcdc_write(priv
, _LDINTR
, (ldintr
^ LDINTR_STATUS_MASK
) & ~LDINTR_VEE
);
360 /* figure out if this interrupt is for main or sub lcd */
361 is_sub
= (lcdc_read(priv
, _LDSR
) & LDSR_MSS
) ? 1 : 0;
363 /* wake up channel and disable clocks */
364 for (k
= 0; k
< ARRAY_SIZE(priv
->ch
); k
++) {
371 if (ldintr
& LDINTR_FS
) {
372 if (is_sub
== lcdc_chan_is_sublcd(ch
)) {
374 wake_up(&ch
->frame_end_wait
);
376 sh_mobile_lcdc_clk_off(priv
);
381 if (ldintr
& LDINTR_VES
)
382 complete(&ch
->vsync_completion
);
388 static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv
*priv
,
391 unsigned long tmp
= lcdc_read(priv
, _LDCNT2R
);
394 /* start or stop the lcdc */
396 lcdc_write(priv
, _LDCNT2R
, tmp
| LDCNT2R_DO
);
398 lcdc_write(priv
, _LDCNT2R
, tmp
& ~LDCNT2R_DO
);
400 /* wait until power is applied/stopped on all channels */
401 for (k
= 0; k
< ARRAY_SIZE(priv
->ch
); k
++)
402 if (lcdc_read(priv
, _LDCNT2R
) & priv
->ch
[k
].enabled
)
404 tmp
= lcdc_read_chan(&priv
->ch
[k
], LDPMR
)
406 if (start
&& tmp
== LDPMR_LPS
)
408 if (!start
&& tmp
== 0)
414 lcdc_write(priv
, _LDDCKSTPR
, 1); /* stop dotclock */
417 static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan
*ch
)
419 struct fb_var_screeninfo
*var
= &ch
->info
->var
, *display_var
= &ch
->display_var
;
420 unsigned long h_total
, hsync_pos
, display_h_total
;
423 tmp
= ch
->ldmt1r_value
;
424 tmp
|= (var
->sync
& FB_SYNC_VERT_HIGH_ACT
) ? 0 : LDMT1R_VPOL
;
425 tmp
|= (var
->sync
& FB_SYNC_HOR_HIGH_ACT
) ? 0 : LDMT1R_HPOL
;
426 tmp
|= (ch
->cfg
.flags
& LCDC_FLAGS_DWPOL
) ? LDMT1R_DWPOL
: 0;
427 tmp
|= (ch
->cfg
.flags
& LCDC_FLAGS_DIPOL
) ? LDMT1R_DIPOL
: 0;
428 tmp
|= (ch
->cfg
.flags
& LCDC_FLAGS_DAPOL
) ? LDMT1R_DAPOL
: 0;
429 tmp
|= (ch
->cfg
.flags
& LCDC_FLAGS_HSCNT
) ? LDMT1R_HSCNT
: 0;
430 tmp
|= (ch
->cfg
.flags
& LCDC_FLAGS_DWCNT
) ? LDMT1R_DWCNT
: 0;
431 lcdc_write_chan(ch
, LDMT1R
, tmp
);
434 lcdc_write_chan(ch
, LDMT2R
, ch
->cfg
.sys_bus_cfg
.ldmt2r
);
435 lcdc_write_chan(ch
, LDMT3R
, ch
->cfg
.sys_bus_cfg
.ldmt3r
);
437 /* horizontal configuration */
438 h_total
= display_var
->xres
+ display_var
->hsync_len
+
439 display_var
->left_margin
+ display_var
->right_margin
;
440 tmp
= h_total
/ 8; /* HTCN */
441 tmp
|= (min(display_var
->xres
, var
->xres
) / 8) << 16; /* HDCN */
442 lcdc_write_chan(ch
, LDHCNR
, tmp
);
444 hsync_pos
= display_var
->xres
+ display_var
->right_margin
;
445 tmp
= hsync_pos
/ 8; /* HSYNP */
446 tmp
|= (display_var
->hsync_len
/ 8) << 16; /* HSYNW */
447 lcdc_write_chan(ch
, LDHSYNR
, tmp
);
449 /* vertical configuration */
450 tmp
= display_var
->yres
+ display_var
->vsync_len
+
451 display_var
->upper_margin
+ display_var
->lower_margin
; /* VTLN */
452 tmp
|= min(display_var
->yres
, var
->yres
) << 16; /* VDLN */
453 lcdc_write_chan(ch
, LDVLNR
, tmp
);
455 tmp
= display_var
->yres
+ display_var
->lower_margin
; /* VSYNP */
456 tmp
|= display_var
->vsync_len
<< 16; /* VSYNW */
457 lcdc_write_chan(ch
, LDVSYNR
, tmp
);
459 /* Adjust horizontal synchronisation for HDMI */
460 display_h_total
= display_var
->xres
+ display_var
->hsync_len
+
461 display_var
->left_margin
+ display_var
->right_margin
;
462 tmp
= ((display_var
->xres
& 7) << 24) |
463 ((display_h_total
& 7) << 16) |
464 ((display_var
->hsync_len
& 7) << 8) |
466 lcdc_write_chan(ch
, LDHAJR
, tmp
);
470 * __sh_mobile_lcdc_start - Configure and tart the LCDC
473 * Configure all enabled channels and start the LCDC device. All external
474 * devices (clocks, MERAM, panels, ...) are not touched by this function.
476 static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv
*priv
)
478 struct sh_mobile_lcdc_chan
*ch
;
482 /* Enable LCDC channels. Read data from external memory, avoid using the
485 lcdc_write(priv
, _LDCNT2R
, priv
->ch
[0].enabled
| priv
->ch
[1].enabled
);
487 /* Stop the LCDC first and disable all interrupts. */
488 sh_mobile_lcdc_start_stop(priv
, 0);
489 lcdc_write(priv
, _LDINTR
, 0);
491 /* Configure power supply, dot clocks and start them. */
493 for (k
= 0; k
< ARRAY_SIZE(priv
->ch
); k
++) {
499 lcdc_write_chan(ch
, LDPMR
, 0);
501 m
= ch
->cfg
.clock_divider
;
505 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
508 lcdc_write_chan(ch
, LDDCKPAT1R
, 0);
509 lcdc_write_chan(ch
, LDDCKPAT2R
, (1 << (m
/2)) - 1);
513 tmp
|= m
<< (lcdc_chan_is_sublcd(ch
) ? 8 : 0);
516 lcdc_write(priv
, _LDDCKR
, tmp
);
517 lcdc_write(priv
, _LDDCKSTPR
, 0);
518 lcdc_wait_bit(priv
, _LDDCKSTPR
, ~0, 0);
520 /* Setup geometry, format, frame buffer memory and operation mode. */
521 for (k
= 0; k
< ARRAY_SIZE(priv
->ch
); k
++) {
526 sh_mobile_lcdc_geometry(ch
);
528 switch (sh_mobile_format_fourcc(&ch
->info
->var
)) {
529 case V4L2_PIX_FMT_RGB565
:
530 tmp
= LDDFR_PKF_RGB16
;
532 case V4L2_PIX_FMT_BGR24
:
533 tmp
= LDDFR_PKF_RGB24
;
535 case V4L2_PIX_FMT_BGR32
:
536 tmp
= LDDFR_PKF_ARGB32
;
538 case V4L2_PIX_FMT_NV12
:
539 case V4L2_PIX_FMT_NV21
:
540 tmp
= LDDFR_CC
| LDDFR_YF_420
;
542 case V4L2_PIX_FMT_NV16
:
543 case V4L2_PIX_FMT_NV61
:
544 tmp
= LDDFR_CC
| LDDFR_YF_422
;
546 case V4L2_PIX_FMT_NV24
:
547 case V4L2_PIX_FMT_NV42
:
548 tmp
= LDDFR_CC
| LDDFR_YF_444
;
552 if (sh_mobile_format_is_yuv(&ch
->info
->var
)) {
553 switch (ch
->info
->var
.colorspace
) {
554 case V4L2_COLORSPACE_REC709
:
557 case V4L2_COLORSPACE_JPEG
:
563 lcdc_write_chan(ch
, LDDFR
, tmp
);
564 lcdc_write_chan(ch
, LDMLSR
, ch
->pitch
);
565 lcdc_write_chan(ch
, LDSA1R
, ch
->base_addr_y
);
566 if (sh_mobile_format_is_yuv(&ch
->info
->var
))
567 lcdc_write_chan(ch
, LDSA2R
, ch
->base_addr_c
);
569 /* When using deferred I/O mode, configure the LCDC for one-shot
570 * operation and enable the frame end interrupt. Otherwise use
571 * continuous read mode.
573 if (ch
->ldmt1r_value
& LDMT1R_IFM
&&
574 ch
->cfg
.sys_bus_cfg
.deferred_io_msec
) {
575 lcdc_write_chan(ch
, LDSM1R
, LDSM1R_OS
);
576 lcdc_write(priv
, _LDINTR
, LDINTR_FE
);
578 lcdc_write_chan(ch
, LDSM1R
, 0);
582 /* Word and long word swap. */
583 switch (sh_mobile_format_fourcc(&priv
->ch
[0].info
->var
)) {
584 case V4L2_PIX_FMT_RGB565
:
585 case V4L2_PIX_FMT_NV21
:
586 case V4L2_PIX_FMT_NV61
:
587 case V4L2_PIX_FMT_NV42
:
588 tmp
= LDDDSR_LS
| LDDDSR_WS
;
590 case V4L2_PIX_FMT_BGR24
:
591 case V4L2_PIX_FMT_NV12
:
592 case V4L2_PIX_FMT_NV16
:
593 case V4L2_PIX_FMT_NV24
:
594 tmp
= LDDDSR_LS
| LDDDSR_WS
| LDDDSR_BS
;
596 case V4L2_PIX_FMT_BGR32
:
601 lcdc_write(priv
, _LDDDSR
, tmp
);
603 /* Enable the display output. */
604 lcdc_write(priv
, _LDCNT1R
, LDCNT1R_DE
);
605 sh_mobile_lcdc_start_stop(priv
, 1);
609 static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv
*priv
)
611 struct sh_mobile_meram_info
*mdev
= priv
->meram_dev
;
612 struct sh_mobile_lcdc_board_cfg
*board_cfg
;
613 struct sh_mobile_lcdc_chan
*ch
;
618 /* enable clocks before accessing the hardware */
619 for (k
= 0; k
< ARRAY_SIZE(priv
->ch
); k
++) {
620 if (priv
->ch
[k
].enabled
)
621 sh_mobile_lcdc_clk_on(priv
);
625 lcdc_write(priv
, _LDCNT2R
, lcdc_read(priv
, _LDCNT2R
) | LDCNT2R_BR
);
626 lcdc_wait_bit(priv
, _LDCNT2R
, LDCNT2R_BR
, 0);
628 for (k
= 0; k
< ARRAY_SIZE(priv
->ch
); k
++) {
634 board_cfg
= &ch
->cfg
.board_cfg
;
635 if (board_cfg
->setup_sys
) {
636 ret
= board_cfg
->setup_sys(board_cfg
->board_data
, ch
,
637 &sh_mobile_lcdc_sys_bus_ops
);
643 /* Compute frame buffer base address and pitch for each channel. */
644 for (k
= 0; k
< ARRAY_SIZE(priv
->ch
); k
++) {
645 struct sh_mobile_meram_cfg
*cfg
;
652 ch
->base_addr_y
= ch
->info
->fix
.smem_start
;
653 ch
->base_addr_c
= ch
->base_addr_y
655 * ch
->info
->var
.yres_virtual
;
656 ch
->pitch
= ch
->info
->fix
.line_length
;
658 /* Enable MERAM if possible. */
659 cfg
= ch
->cfg
.meram_cfg
;
660 if (mdev
== NULL
|| mdev
->ops
== NULL
|| cfg
== NULL
)
663 /* we need to de-init configured ICBs before we can
664 * re-initialize them.
666 if (ch
->meram_enabled
) {
667 mdev
->ops
->meram_unregister(mdev
, cfg
);
668 ch
->meram_enabled
= 0;
671 switch (sh_mobile_format_fourcc(&ch
->info
->var
)) {
672 case V4L2_PIX_FMT_NV12
:
673 case V4L2_PIX_FMT_NV21
:
674 case V4L2_PIX_FMT_NV16
:
675 case V4L2_PIX_FMT_NV61
:
676 pixelformat
= SH_MOBILE_MERAM_PF_NV
;
678 case V4L2_PIX_FMT_NV24
:
679 case V4L2_PIX_FMT_NV42
:
680 pixelformat
= SH_MOBILE_MERAM_PF_NV24
;
682 case V4L2_PIX_FMT_RGB565
:
683 case V4L2_PIX_FMT_BGR24
:
684 case V4L2_PIX_FMT_BGR32
:
686 pixelformat
= SH_MOBILE_MERAM_PF_RGB
;
690 ret
= mdev
->ops
->meram_register(mdev
, cfg
, ch
->pitch
,
691 ch
->info
->var
.yres
, pixelformat
,
692 ch
->base_addr_y
, ch
->base_addr_c
,
693 &ch
->base_addr_y
, &ch
->base_addr_c
,
696 ch
->meram_enabled
= 1;
699 /* Start the LCDC. */
700 __sh_mobile_lcdc_start(priv
);
702 /* Setup deferred I/O, tell the board code to enable the panels, and
705 for (k
= 0; k
< ARRAY_SIZE(priv
->ch
); k
++) {
710 tmp
= ch
->cfg
.sys_bus_cfg
.deferred_io_msec
;
711 if (ch
->ldmt1r_value
& LDMT1R_IFM
&& tmp
) {
712 ch
->defio
.deferred_io
= sh_mobile_lcdc_deferred_io
;
713 ch
->defio
.delay
= msecs_to_jiffies(tmp
);
714 ch
->info
->fbdefio
= &ch
->defio
;
715 fb_deferred_io_init(ch
->info
);
718 board_cfg
= &ch
->cfg
.board_cfg
;
719 if (board_cfg
->display_on
&& try_module_get(board_cfg
->owner
)) {
720 board_cfg
->display_on(board_cfg
->board_data
, ch
->info
);
721 module_put(board_cfg
->owner
);
725 ch
->bl
->props
.power
= FB_BLANK_UNBLANK
;
726 backlight_update_status(ch
->bl
);
733 static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv
*priv
)
735 struct sh_mobile_lcdc_chan
*ch
;
736 struct sh_mobile_lcdc_board_cfg
*board_cfg
;
739 /* clean up deferred io and ask board code to disable panel */
740 for (k
= 0; k
< ARRAY_SIZE(priv
->ch
); k
++) {
746 * flush frame, and wait for frame end interrupt
747 * clean up deferred io and enable clock
749 if (ch
->info
&& ch
->info
->fbdefio
) {
751 schedule_delayed_work(&ch
->info
->deferred_work
, 0);
752 wait_event(ch
->frame_end_wait
, ch
->frame_end
);
753 fb_deferred_io_cleanup(ch
->info
);
754 ch
->info
->fbdefio
= NULL
;
755 sh_mobile_lcdc_clk_on(priv
);
759 ch
->bl
->props
.power
= FB_BLANK_POWERDOWN
;
760 backlight_update_status(ch
->bl
);
763 board_cfg
= &ch
->cfg
.board_cfg
;
764 if (board_cfg
->display_off
&& try_module_get(board_cfg
->owner
)) {
765 board_cfg
->display_off(board_cfg
->board_data
);
766 module_put(board_cfg
->owner
);
769 /* disable the meram */
770 if (ch
->meram_enabled
) {
771 struct sh_mobile_meram_cfg
*cfg
;
772 struct sh_mobile_meram_info
*mdev
;
773 cfg
= ch
->cfg
.meram_cfg
;
774 mdev
= priv
->meram_dev
;
775 mdev
->ops
->meram_unregister(mdev
, cfg
);
776 ch
->meram_enabled
= 0;
783 sh_mobile_lcdc_start_stop(priv
, 0);
788 for (k
= 0; k
< ARRAY_SIZE(priv
->ch
); k
++)
789 if (priv
->ch
[k
].enabled
)
790 sh_mobile_lcdc_clk_off(priv
);
793 static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan
*ch
)
795 int interface_type
= ch
->cfg
.interface_type
;
797 switch (interface_type
) {
821 /* SUBLCD only supports SYS interface */
822 if (lcdc_chan_is_sublcd(ch
)) {
823 if (!(interface_type
& LDMT1R_IFM
))
826 interface_type
&= ~LDMT1R_IFM
;
829 ch
->ldmt1r_value
= interface_type
;
833 static int sh_mobile_lcdc_setup_clocks(struct platform_device
*pdev
,
835 struct sh_mobile_lcdc_priv
*priv
)
839 switch (clock_source
) {
842 priv
->lddckr
= LDDCKR_ICKSEL_BUS
;
844 case LCDC_CLK_PERIPHERAL
:
845 str
= "peripheral_clk";
846 priv
->lddckr
= LDDCKR_ICKSEL_MIPI
;
848 case LCDC_CLK_EXTERNAL
:
850 priv
->lddckr
= LDDCKR_ICKSEL_HDMI
;
857 priv
->dot_clk
= clk_get(&pdev
->dev
, str
);
858 if (IS_ERR(priv
->dot_clk
)) {
859 dev_err(&pdev
->dev
, "cannot get dot clock %s\n", str
);
860 return PTR_ERR(priv
->dot_clk
);
864 /* Runtime PM support involves two step for this driver:
865 * 1) Enable Runtime PM
866 * 2) Force Runtime PM Resume since hardware is accessed from probe()
868 priv
->dev
= &pdev
->dev
;
869 pm_runtime_enable(priv
->dev
);
870 pm_runtime_resume(priv
->dev
);
874 static int sh_mobile_lcdc_setcolreg(u_int regno
,
875 u_int red
, u_int green
, u_int blue
,
876 u_int transp
, struct fb_info
*info
)
878 u32
*palette
= info
->pseudo_palette
;
880 if (regno
>= PALETTE_NR
)
883 /* only FB_VISUAL_TRUECOLOR supported */
885 red
>>= 16 - info
->var
.red
.length
;
886 green
>>= 16 - info
->var
.green
.length
;
887 blue
>>= 16 - info
->var
.blue
.length
;
888 transp
>>= 16 - info
->var
.transp
.length
;
890 palette
[regno
] = (red
<< info
->var
.red
.offset
) |
891 (green
<< info
->var
.green
.offset
) |
892 (blue
<< info
->var
.blue
.offset
) |
893 (transp
<< info
->var
.transp
.offset
);
898 static struct fb_fix_screeninfo sh_mobile_lcdc_fix
= {
899 .id
= "SH Mobile LCDC",
900 .type
= FB_TYPE_PACKED_PIXELS
,
901 .visual
= FB_VISUAL_TRUECOLOR
,
902 .accel
= FB_ACCEL_NONE
,
906 .capabilities
= FB_CAP_FOURCC
,
909 static void sh_mobile_lcdc_fillrect(struct fb_info
*info
,
910 const struct fb_fillrect
*rect
)
912 sys_fillrect(info
, rect
);
913 sh_mobile_lcdc_deferred_io_touch(info
);
916 static void sh_mobile_lcdc_copyarea(struct fb_info
*info
,
917 const struct fb_copyarea
*area
)
919 sys_copyarea(info
, area
);
920 sh_mobile_lcdc_deferred_io_touch(info
);
923 static void sh_mobile_lcdc_imageblit(struct fb_info
*info
,
924 const struct fb_image
*image
)
926 sys_imageblit(info
, image
);
927 sh_mobile_lcdc_deferred_io_touch(info
);
930 static int sh_mobile_fb_pan_display(struct fb_var_screeninfo
*var
,
931 struct fb_info
*info
)
933 struct sh_mobile_lcdc_chan
*ch
= info
->par
;
934 struct sh_mobile_lcdc_priv
*priv
= ch
->lcdc
;
935 unsigned long ldrcntr
;
936 unsigned long new_pan_offset
;
937 unsigned long base_addr_y
, base_addr_c
;
938 unsigned long c_offset
;
939 bool yuv
= sh_mobile_format_is_yuv(&info
->var
);
942 new_pan_offset
= var
->yoffset
* info
->fix
.line_length
943 + var
->xoffset
* (info
->var
.bits_per_pixel
/ 8);
945 new_pan_offset
= var
->yoffset
* info
->fix
.line_length
948 if (new_pan_offset
== ch
->pan_offset
)
949 return 0; /* No change, do nothing */
951 ldrcntr
= lcdc_read(priv
, _LDRCNTR
);
953 /* Set the source address for the next refresh */
954 base_addr_y
= ch
->dma_handle
+ new_pan_offset
;
957 c_offset
= var
->yoffset
* info
->fix
.line_length
958 * (info
->var
.bits_per_pixel
- 8) / 8;
959 base_addr_c
= ch
->dma_handle
960 + info
->var
.xres
* info
->var
.yres_virtual
963 if (sh_mobile_format_fourcc(&info
->var
) == V4L2_PIX_FMT_NV24
)
964 base_addr_c
+= 2 * var
->xoffset
;
966 base_addr_c
+= var
->xoffset
;
969 if (ch
->meram_enabled
) {
970 struct sh_mobile_meram_cfg
*cfg
;
971 struct sh_mobile_meram_info
*mdev
;
974 cfg
= ch
->cfg
.meram_cfg
;
975 mdev
= priv
->meram_dev
;
976 ret
= mdev
->ops
->meram_update(mdev
, cfg
,
977 base_addr_y
, base_addr_c
,
978 &base_addr_y
, &base_addr_c
);
983 ch
->base_addr_y
= base_addr_y
;
984 ch
->base_addr_c
= base_addr_c
;
986 lcdc_write_chan_mirror(ch
, LDSA1R
, base_addr_y
);
988 lcdc_write_chan_mirror(ch
, LDSA2R
, base_addr_c
);
990 if (lcdc_chan_is_sublcd(ch
))
991 lcdc_write(ch
->lcdc
, _LDRCNTR
, ldrcntr
^ LDRCNTR_SRS
);
993 lcdc_write(ch
->lcdc
, _LDRCNTR
, ldrcntr
^ LDRCNTR_MRS
);
995 ch
->pan_offset
= new_pan_offset
;
997 sh_mobile_lcdc_deferred_io_touch(info
);
1002 static int sh_mobile_wait_for_vsync(struct fb_info
*info
)
1004 struct sh_mobile_lcdc_chan
*ch
= info
->par
;
1005 unsigned long ldintr
;
1008 /* Enable VSync End interrupt and be careful not to acknowledge any
1009 * pending interrupt.
1011 ldintr
= lcdc_read(ch
->lcdc
, _LDINTR
);
1012 ldintr
|= LDINTR_VEE
| LDINTR_STATUS_MASK
;
1013 lcdc_write(ch
->lcdc
, _LDINTR
, ldintr
);
1015 ret
= wait_for_completion_interruptible_timeout(&ch
->vsync_completion
,
1016 msecs_to_jiffies(100));
1023 static int sh_mobile_ioctl(struct fb_info
*info
, unsigned int cmd
,
1029 case FBIO_WAITFORVSYNC
:
1030 retval
= sh_mobile_wait_for_vsync(info
);
1034 retval
= -ENOIOCTLCMD
;
1040 static void sh_mobile_fb_reconfig(struct fb_info
*info
)
1042 struct sh_mobile_lcdc_chan
*ch
= info
->par
;
1043 struct fb_videomode mode1
, mode2
;
1044 struct fb_event event
;
1045 int evnt
= FB_EVENT_MODE_CHANGE_ALL
;
1047 if (ch
->use_count
> 1 || (ch
->use_count
== 1 && !info
->fbcon_par
))
1048 /* More framebuffer users are active */
1051 fb_var_to_videomode(&mode1
, &ch
->display_var
);
1052 fb_var_to_videomode(&mode2
, &info
->var
);
1054 if (fb_mode_is_equal(&mode1
, &mode2
))
1057 /* Display has been re-plugged, framebuffer is free now, reconfigure */
1058 if (fb_set_var(info
, &ch
->display_var
) < 0)
1059 /* Couldn't reconfigure, hopefully, can continue as before */
1063 * fb_set_var() calls the notifier change internally, only if
1064 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
1065 * user event, we have to call the chain ourselves.
1068 event
.data
= &mode1
;
1069 fb_notifier_call_chain(evnt
, &event
);
1073 * Locking: both .fb_release() and .fb_open() are called with info->lock held if
1074 * user == 1, or with console sem held, if user == 0.
1076 static int sh_mobile_release(struct fb_info
*info
, int user
)
1078 struct sh_mobile_lcdc_chan
*ch
= info
->par
;
1080 mutex_lock(&ch
->open_lock
);
1081 dev_dbg(info
->dev
, "%s(): %d users\n", __func__
, ch
->use_count
);
1085 /* Nothing to reconfigure, when called from fbcon */
1088 sh_mobile_fb_reconfig(info
);
1092 mutex_unlock(&ch
->open_lock
);
1097 static int sh_mobile_open(struct fb_info
*info
, int user
)
1099 struct sh_mobile_lcdc_chan
*ch
= info
->par
;
1101 mutex_lock(&ch
->open_lock
);
1104 dev_dbg(info
->dev
, "%s(): %d users\n", __func__
, ch
->use_count
);
1105 mutex_unlock(&ch
->open_lock
);
1110 static int sh_mobile_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1112 struct sh_mobile_lcdc_chan
*ch
= info
->par
;
1113 struct sh_mobile_lcdc_priv
*p
= ch
->lcdc
;
1114 unsigned int best_dist
= (unsigned int)-1;
1115 unsigned int best_xres
= 0;
1116 unsigned int best_yres
= 0;
1119 if (var
->xres
> MAX_XRES
|| var
->yres
> MAX_YRES
)
1122 /* If board code provides us with a list of available modes, make sure
1123 * we use one of them. Find the mode closest to the requested one. The
1124 * distance between two modes is defined as the size of the
1125 * non-overlapping parts of the two rectangles.
1127 for (i
= 0; i
< ch
->cfg
.num_cfg
; ++i
) {
1128 const struct fb_videomode
*mode
= &ch
->cfg
.lcd_cfg
[i
];
1131 /* We can only round up. */
1132 if (var
->xres
> mode
->xres
|| var
->yres
> mode
->yres
)
1135 dist
= var
->xres
* var
->yres
+ mode
->xres
* mode
->yres
1136 - 2 * min(var
->xres
, mode
->xres
)
1137 * min(var
->yres
, mode
->yres
);
1139 if (dist
< best_dist
) {
1140 best_xres
= mode
->xres
;
1141 best_yres
= mode
->yres
;
1146 /* If no available mode can be used, return an error. */
1147 if (ch
->cfg
.num_cfg
!= 0) {
1148 if (best_dist
== (unsigned int)-1)
1151 var
->xres
= best_xres
;
1152 var
->yres
= best_yres
;
1155 /* Make sure the virtual resolution is at least as big as the visible
1158 if (var
->xres_virtual
< var
->xres
)
1159 var
->xres_virtual
= var
->xres
;
1160 if (var
->yres_virtual
< var
->yres
)
1161 var
->yres_virtual
= var
->yres
;
1163 if (sh_mobile_format_is_fourcc(var
)) {
1164 switch (var
->grayscale
) {
1165 case V4L2_PIX_FMT_NV12
:
1166 case V4L2_PIX_FMT_NV21
:
1167 var
->bits_per_pixel
= 12;
1169 case V4L2_PIX_FMT_RGB565
:
1170 case V4L2_PIX_FMT_NV16
:
1171 case V4L2_PIX_FMT_NV61
:
1172 var
->bits_per_pixel
= 16;
1174 case V4L2_PIX_FMT_BGR24
:
1175 case V4L2_PIX_FMT_NV24
:
1176 case V4L2_PIX_FMT_NV42
:
1177 var
->bits_per_pixel
= 24;
1179 case V4L2_PIX_FMT_BGR32
:
1180 var
->bits_per_pixel
= 32;
1186 /* Default to RGB and JPEG color-spaces for RGB and YUV formats
1189 if (!sh_mobile_format_is_yuv(var
))
1190 var
->colorspace
= V4L2_COLORSPACE_SRGB
;
1191 else if (var
->colorspace
!= V4L2_COLORSPACE_REC709
)
1192 var
->colorspace
= V4L2_COLORSPACE_JPEG
;
1194 if (var
->bits_per_pixel
<= 16) { /* RGB 565 */
1195 var
->bits_per_pixel
= 16;
1196 var
->red
.offset
= 11;
1197 var
->red
.length
= 5;
1198 var
->green
.offset
= 5;
1199 var
->green
.length
= 6;
1200 var
->blue
.offset
= 0;
1201 var
->blue
.length
= 5;
1202 var
->transp
.offset
= 0;
1203 var
->transp
.length
= 0;
1204 } else if (var
->bits_per_pixel
<= 24) { /* RGB 888 */
1205 var
->bits_per_pixel
= 24;
1206 var
->red
.offset
= 16;
1207 var
->red
.length
= 8;
1208 var
->green
.offset
= 8;
1209 var
->green
.length
= 8;
1210 var
->blue
.offset
= 0;
1211 var
->blue
.length
= 8;
1212 var
->transp
.offset
= 0;
1213 var
->transp
.length
= 0;
1214 } else if (var
->bits_per_pixel
<= 32) { /* RGBA 888 */
1215 var
->bits_per_pixel
= 32;
1216 var
->red
.offset
= 16;
1217 var
->red
.length
= 8;
1218 var
->green
.offset
= 8;
1219 var
->green
.length
= 8;
1220 var
->blue
.offset
= 0;
1221 var
->blue
.length
= 8;
1222 var
->transp
.offset
= 24;
1223 var
->transp
.length
= 8;
1227 var
->red
.msb_right
= 0;
1228 var
->green
.msb_right
= 0;
1229 var
->blue
.msb_right
= 0;
1230 var
->transp
.msb_right
= 0;
1233 /* Make sure we don't exceed our allocated memory. */
1234 if (var
->xres_virtual
* var
->yres_virtual
* var
->bits_per_pixel
/ 8 >
1238 /* only accept the forced_fourcc for dual channel configurations */
1239 if (p
->forced_fourcc
&&
1240 p
->forced_fourcc
!= sh_mobile_format_fourcc(var
))
1246 static int sh_mobile_set_par(struct fb_info
*info
)
1248 struct sh_mobile_lcdc_chan
*ch
= info
->par
;
1249 u32 line_length
= info
->fix
.line_length
;
1252 sh_mobile_lcdc_stop(ch
->lcdc
);
1254 if (sh_mobile_format_is_yuv(&info
->var
))
1255 info
->fix
.line_length
= info
->var
.xres
;
1257 info
->fix
.line_length
= info
->var
.xres
1258 * info
->var
.bits_per_pixel
/ 8;
1260 ret
= sh_mobile_lcdc_start(ch
->lcdc
);
1262 dev_err(info
->dev
, "%s: unable to restart LCDC\n", __func__
);
1263 info
->fix
.line_length
= line_length
;
1266 if (sh_mobile_format_is_fourcc(&info
->var
)) {
1267 info
->fix
.type
= FB_TYPE_FOURCC
;
1268 info
->fix
.visual
= FB_VISUAL_FOURCC
;
1270 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
1271 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
1278 * Screen blanking. Behavior is as follows:
1279 * FB_BLANK_UNBLANK: screen unblanked, clocks enabled
1280 * FB_BLANK_NORMAL: screen blanked, clocks enabled
1283 * FB_BLANK_POWEROFF: screen blanked, clocks disabled
1285 static int sh_mobile_lcdc_blank(int blank
, struct fb_info
*info
)
1287 struct sh_mobile_lcdc_chan
*ch
= info
->par
;
1288 struct sh_mobile_lcdc_priv
*p
= ch
->lcdc
;
1290 /* blank the screen? */
1291 if (blank
> FB_BLANK_UNBLANK
&& ch
->blank_status
== FB_BLANK_UNBLANK
) {
1292 struct fb_fillrect rect
= {
1293 .width
= info
->var
.xres
,
1294 .height
= info
->var
.yres
,
1296 sh_mobile_lcdc_fillrect(info
, &rect
);
1298 /* turn clocks on? */
1299 if (blank
<= FB_BLANK_NORMAL
&& ch
->blank_status
> FB_BLANK_NORMAL
) {
1300 sh_mobile_lcdc_clk_on(p
);
1302 /* turn clocks off? */
1303 if (blank
> FB_BLANK_NORMAL
&& ch
->blank_status
<= FB_BLANK_NORMAL
) {
1304 /* make sure the screen is updated with the black fill before
1305 * switching the clocks off. one vsync is not enough since
1306 * blanking may occur in the middle of a refresh. deferred io
1307 * mode will reenable the clocks and update the screen in time,
1308 * so it does not need this. */
1309 if (!info
->fbdefio
) {
1310 sh_mobile_wait_for_vsync(info
);
1311 sh_mobile_wait_for_vsync(info
);
1313 sh_mobile_lcdc_clk_off(p
);
1316 ch
->blank_status
= blank
;
1320 static struct fb_ops sh_mobile_lcdc_ops
= {
1321 .owner
= THIS_MODULE
,
1322 .fb_setcolreg
= sh_mobile_lcdc_setcolreg
,
1323 .fb_read
= fb_sys_read
,
1324 .fb_write
= fb_sys_write
,
1325 .fb_fillrect
= sh_mobile_lcdc_fillrect
,
1326 .fb_copyarea
= sh_mobile_lcdc_copyarea
,
1327 .fb_imageblit
= sh_mobile_lcdc_imageblit
,
1328 .fb_blank
= sh_mobile_lcdc_blank
,
1329 .fb_pan_display
= sh_mobile_fb_pan_display
,
1330 .fb_ioctl
= sh_mobile_ioctl
,
1331 .fb_open
= sh_mobile_open
,
1332 .fb_release
= sh_mobile_release
,
1333 .fb_check_var
= sh_mobile_check_var
,
1334 .fb_set_par
= sh_mobile_set_par
,
1337 static int sh_mobile_lcdc_update_bl(struct backlight_device
*bdev
)
1339 struct sh_mobile_lcdc_chan
*ch
= bl_get_data(bdev
);
1340 struct sh_mobile_lcdc_board_cfg
*cfg
= &ch
->cfg
.board_cfg
;
1341 int brightness
= bdev
->props
.brightness
;
1343 if (bdev
->props
.power
!= FB_BLANK_UNBLANK
||
1344 bdev
->props
.state
& (BL_CORE_SUSPENDED
| BL_CORE_FBBLANK
))
1347 return cfg
->set_brightness(cfg
->board_data
, brightness
);
1350 static int sh_mobile_lcdc_get_brightness(struct backlight_device
*bdev
)
1352 struct sh_mobile_lcdc_chan
*ch
= bl_get_data(bdev
);
1353 struct sh_mobile_lcdc_board_cfg
*cfg
= &ch
->cfg
.board_cfg
;
1355 return cfg
->get_brightness(cfg
->board_data
);
1358 static int sh_mobile_lcdc_check_fb(struct backlight_device
*bdev
,
1359 struct fb_info
*info
)
1361 return (info
->bl_dev
== bdev
);
1364 static struct backlight_ops sh_mobile_lcdc_bl_ops
= {
1365 .options
= BL_CORE_SUSPENDRESUME
,
1366 .update_status
= sh_mobile_lcdc_update_bl
,
1367 .get_brightness
= sh_mobile_lcdc_get_brightness
,
1368 .check_fb
= sh_mobile_lcdc_check_fb
,
1371 static struct backlight_device
*sh_mobile_lcdc_bl_probe(struct device
*parent
,
1372 struct sh_mobile_lcdc_chan
*ch
)
1374 struct backlight_device
*bl
;
1376 bl
= backlight_device_register(ch
->cfg
.bl_info
.name
, parent
, ch
,
1377 &sh_mobile_lcdc_bl_ops
, NULL
);
1379 dev_err(parent
, "unable to register backlight device: %ld\n",
1384 bl
->props
.max_brightness
= ch
->cfg
.bl_info
.max_brightness
;
1385 bl
->props
.brightness
= bl
->props
.max_brightness
;
1386 backlight_update_status(bl
);
1391 static void sh_mobile_lcdc_bl_remove(struct backlight_device
*bdev
)
1393 backlight_device_unregister(bdev
);
1396 static int sh_mobile_lcdc_suspend(struct device
*dev
)
1398 struct platform_device
*pdev
= to_platform_device(dev
);
1400 sh_mobile_lcdc_stop(platform_get_drvdata(pdev
));
1404 static int sh_mobile_lcdc_resume(struct device
*dev
)
1406 struct platform_device
*pdev
= to_platform_device(dev
);
1408 return sh_mobile_lcdc_start(platform_get_drvdata(pdev
));
1411 static int sh_mobile_lcdc_runtime_suspend(struct device
*dev
)
1413 struct platform_device
*pdev
= to_platform_device(dev
);
1414 struct sh_mobile_lcdc_priv
*priv
= platform_get_drvdata(pdev
);
1416 /* turn off LCDC hardware */
1417 lcdc_write(priv
, _LDCNT1R
, 0);
1422 static int sh_mobile_lcdc_runtime_resume(struct device
*dev
)
1424 struct platform_device
*pdev
= to_platform_device(dev
);
1425 struct sh_mobile_lcdc_priv
*priv
= platform_get_drvdata(pdev
);
1427 __sh_mobile_lcdc_start(priv
);
1432 static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops
= {
1433 .suspend
= sh_mobile_lcdc_suspend
,
1434 .resume
= sh_mobile_lcdc_resume
,
1435 .runtime_suspend
= sh_mobile_lcdc_runtime_suspend
,
1436 .runtime_resume
= sh_mobile_lcdc_runtime_resume
,
1439 /* locking: called with info->lock held */
1440 static int sh_mobile_lcdc_notify(struct notifier_block
*nb
,
1441 unsigned long action
, void *data
)
1443 struct fb_event
*event
= data
;
1444 struct fb_info
*info
= event
->info
;
1445 struct sh_mobile_lcdc_chan
*ch
= info
->par
;
1446 struct sh_mobile_lcdc_board_cfg
*board_cfg
= &ch
->cfg
.board_cfg
;
1448 if (&ch
->lcdc
->notifier
!= nb
)
1451 dev_dbg(info
->dev
, "%s(): action = %lu, data = %p\n",
1452 __func__
, action
, event
->data
);
1455 case FB_EVENT_SUSPEND
:
1456 if (board_cfg
->display_off
&& try_module_get(board_cfg
->owner
)) {
1457 board_cfg
->display_off(board_cfg
->board_data
);
1458 module_put(board_cfg
->owner
);
1460 sh_mobile_lcdc_stop(ch
->lcdc
);
1462 case FB_EVENT_RESUME
:
1463 mutex_lock(&ch
->open_lock
);
1464 sh_mobile_fb_reconfig(info
);
1465 mutex_unlock(&ch
->open_lock
);
1467 /* HDMI must be enabled before LCDC configuration */
1468 if (board_cfg
->display_on
&& try_module_get(board_cfg
->owner
)) {
1469 board_cfg
->display_on(board_cfg
->board_data
, info
);
1470 module_put(board_cfg
->owner
);
1473 sh_mobile_lcdc_start(ch
->lcdc
);
1479 static int sh_mobile_lcdc_remove(struct platform_device
*pdev
)
1481 struct sh_mobile_lcdc_priv
*priv
= platform_get_drvdata(pdev
);
1482 struct fb_info
*info
;
1485 fb_unregister_client(&priv
->notifier
);
1487 for (i
= 0; i
< ARRAY_SIZE(priv
->ch
); i
++)
1488 if (priv
->ch
[i
].info
&& priv
->ch
[i
].info
->dev
)
1489 unregister_framebuffer(priv
->ch
[i
].info
);
1491 sh_mobile_lcdc_stop(priv
);
1493 for (i
= 0; i
< ARRAY_SIZE(priv
->ch
); i
++) {
1494 info
= priv
->ch
[i
].info
;
1496 if (!info
|| !info
->device
)
1499 if (priv
->ch
[i
].sglist
)
1500 vfree(priv
->ch
[i
].sglist
);
1502 if (info
->screen_base
)
1503 dma_free_coherent(&pdev
->dev
, info
->fix
.smem_len
,
1505 priv
->ch
[i
].dma_handle
);
1506 fb_dealloc_cmap(&info
->cmap
);
1507 framebuffer_release(info
);
1510 for (i
= 0; i
< ARRAY_SIZE(priv
->ch
); i
++) {
1512 sh_mobile_lcdc_bl_remove(priv
->ch
[i
].bl
);
1516 clk_put(priv
->dot_clk
);
1519 pm_runtime_disable(priv
->dev
);
1522 iounmap(priv
->base
);
1525 free_irq(priv
->irq
, priv
);
1530 static int __devinit
sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan
*ch
,
1533 struct sh_mobile_lcdc_chan_cfg
*cfg
= &ch
->cfg
;
1534 const struct fb_videomode
*max_mode
;
1535 const struct fb_videomode
*mode
;
1536 struct fb_var_screeninfo
*var
;
1537 struct fb_info
*info
;
1538 unsigned int max_size
;
1544 mutex_init(&ch
->open_lock
);
1546 /* Allocate the frame buffer device. */
1547 ch
->info
= framebuffer_alloc(0, dev
);
1549 dev_err(dev
, "unable to allocate fb_info\n");
1554 info
->fbops
= &sh_mobile_lcdc_ops
;
1556 info
->pseudo_palette
= &ch
->pseudo_palette
;
1557 info
->flags
= FBINFO_FLAG_DEFAULT
;
1559 /* Iterate through the modes to validate them and find the highest
1565 for (i
= 0, mode
= cfg
->lcd_cfg
; i
< cfg
->num_cfg
; i
++, mode
++) {
1566 unsigned int size
= mode
->yres
* mode
->xres
;
1568 /* NV12/NV21 buffers must have even number of lines */
1569 if ((cfg
->fourcc
== V4L2_PIX_FMT_NV12
||
1570 cfg
->fourcc
== V4L2_PIX_FMT_NV21
) && (mode
->yres
& 0x1)) {
1571 dev_err(dev
, "yres must be multiple of 2 for YCbCr420 "
1576 if (size
> max_size
) {
1583 max_size
= MAX_XRES
* MAX_YRES
;
1585 dev_dbg(dev
, "Found largest videomode %ux%u\n",
1586 max_mode
->xres
, max_mode
->yres
);
1588 /* Create the mode list. */
1589 if (cfg
->lcd_cfg
== NULL
) {
1590 mode
= &default_720p
;
1593 mode
= cfg
->lcd_cfg
;
1594 num_cfg
= cfg
->num_cfg
;
1597 fb_videomode_to_modelist(mode
, num_cfg
, &info
->modelist
);
1599 /* Initialize variable screen information using the first mode as
1600 * default. The default Y virtual resolution is twice the panel size to
1601 * allow for double-buffering.
1604 fb_videomode_to_var(var
, mode
);
1605 var
->width
= cfg
->lcd_size_cfg
.width
;
1606 var
->height
= cfg
->lcd_size_cfg
.height
;
1607 var
->yres_virtual
= var
->yres
* 2;
1608 var
->activate
= FB_ACTIVATE_NOW
;
1610 switch (cfg
->fourcc
) {
1611 case V4L2_PIX_FMT_RGB565
:
1612 var
->bits_per_pixel
= 16;
1614 case V4L2_PIX_FMT_BGR24
:
1615 var
->bits_per_pixel
= 24;
1617 case V4L2_PIX_FMT_BGR32
:
1618 var
->bits_per_pixel
= 32;
1621 var
->grayscale
= cfg
->fourcc
;
1625 /* Make sure the memory size check won't fail. smem_len is initialized
1626 * later based on var.
1628 info
->fix
.smem_len
= UINT_MAX
;
1629 ret
= sh_mobile_check_var(var
, info
);
1633 max_size
= max_size
* var
->bits_per_pixel
/ 8 * 2;
1635 /* Allocate frame buffer memory and color map. */
1636 buf
= dma_alloc_coherent(dev
, max_size
, &ch
->dma_handle
, GFP_KERNEL
);
1638 dev_err(dev
, "unable to allocate buffer\n");
1642 ret
= fb_alloc_cmap(&info
->cmap
, PALETTE_NR
, 0);
1644 dev_err(dev
, "unable to allocate cmap\n");
1645 dma_free_coherent(dev
, max_size
, buf
, ch
->dma_handle
);
1649 /* Initialize fixed screen information. Restrict pan to 2 lines steps
1650 * for NV12 and NV21.
1652 info
->fix
= sh_mobile_lcdc_fix
;
1653 info
->fix
.smem_start
= ch
->dma_handle
;
1654 info
->fix
.smem_len
= max_size
;
1655 if (cfg
->fourcc
== V4L2_PIX_FMT_NV12
||
1656 cfg
->fourcc
== V4L2_PIX_FMT_NV21
)
1657 info
->fix
.ypanstep
= 2;
1659 if (sh_mobile_format_is_yuv(var
)) {
1660 info
->fix
.line_length
= var
->xres
;
1661 info
->fix
.visual
= FB_VISUAL_FOURCC
;
1663 info
->fix
.line_length
= var
->xres
* var
->bits_per_pixel
/ 8;
1664 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
1667 info
->screen_base
= buf
;
1669 ch
->display_var
= *var
;
1674 static int __devinit
sh_mobile_lcdc_probe(struct platform_device
*pdev
)
1676 struct sh_mobile_lcdc_info
*pdata
= pdev
->dev
.platform_data
;
1677 struct sh_mobile_lcdc_priv
*priv
;
1678 struct resource
*res
;
1684 dev_err(&pdev
->dev
, "no platform data defined\n");
1688 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1689 i
= platform_get_irq(pdev
, 0);
1690 if (!res
|| i
< 0) {
1691 dev_err(&pdev
->dev
, "cannot get platform resources\n");
1695 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
1697 dev_err(&pdev
->dev
, "cannot allocate device data\n");
1701 platform_set_drvdata(pdev
, priv
);
1703 error
= request_irq(i
, sh_mobile_lcdc_irq
, 0,
1704 dev_name(&pdev
->dev
), priv
);
1706 dev_err(&pdev
->dev
, "unable to request irq\n");
1711 atomic_set(&priv
->hw_usecnt
, -1);
1713 for (i
= 0, num_channels
= 0; i
< ARRAY_SIZE(pdata
->ch
); i
++) {
1714 struct sh_mobile_lcdc_chan
*ch
= priv
->ch
+ num_channels
;
1717 memcpy(&ch
->cfg
, &pdata
->ch
[i
], sizeof(pdata
->ch
[i
]));
1719 error
= sh_mobile_lcdc_check_interface(ch
);
1721 dev_err(&pdev
->dev
, "unsupported interface type\n");
1724 init_waitqueue_head(&ch
->frame_end_wait
);
1725 init_completion(&ch
->vsync_completion
);
1728 /* probe the backlight is there is one defined */
1729 if (ch
->cfg
.bl_info
.max_brightness
)
1730 ch
->bl
= sh_mobile_lcdc_bl_probe(&pdev
->dev
, ch
);
1732 switch (pdata
->ch
[i
].chan
) {
1733 case LCDC_CHAN_MAINLCD
:
1734 ch
->enabled
= LDCNT2R_ME
;
1735 ch
->reg_offs
= lcdc_offs_mainlcd
;
1738 case LCDC_CHAN_SUBLCD
:
1739 ch
->enabled
= LDCNT2R_SE
;
1740 ch
->reg_offs
= lcdc_offs_sublcd
;
1746 if (!num_channels
) {
1747 dev_err(&pdev
->dev
, "no channels defined\n");
1752 /* for dual channel LCDC (MAIN + SUB) force shared format setting */
1753 if (num_channels
== 2)
1754 priv
->forced_fourcc
= pdata
->ch
[0].fourcc
;
1756 priv
->base
= ioremap_nocache(res
->start
, resource_size(res
));
1760 error
= sh_mobile_lcdc_setup_clocks(pdev
, pdata
->clock_source
, priv
);
1762 dev_err(&pdev
->dev
, "unable to setup clocks\n");
1766 priv
->meram_dev
= pdata
->meram_dev
;
1768 for (i
= 0; i
< num_channels
; i
++) {
1769 struct sh_mobile_lcdc_chan
*ch
= priv
->ch
+ i
;
1771 error
= sh_mobile_lcdc_channel_init(ch
, &pdev
->dev
);
1776 error
= sh_mobile_lcdc_start(priv
);
1778 dev_err(&pdev
->dev
, "unable to start hardware\n");
1782 for (i
= 0; i
< num_channels
; i
++) {
1783 struct sh_mobile_lcdc_chan
*ch
= priv
->ch
+ i
;
1784 struct fb_info
*info
= ch
->info
;
1786 if (info
->fbdefio
) {
1787 ch
->sglist
= vmalloc(sizeof(struct scatterlist
) *
1788 info
->fix
.smem_len
>> PAGE_SHIFT
);
1790 dev_err(&pdev
->dev
, "cannot allocate sglist\n");
1795 info
->bl_dev
= ch
->bl
;
1797 error
= register_framebuffer(info
);
1801 dev_info(info
->dev
, "registered %s/%s as %dx%d %dbpp.\n",
1802 pdev
->name
, (ch
->cfg
.chan
== LCDC_CHAN_MAINLCD
) ?
1803 "mainlcd" : "sublcd", info
->var
.xres
, info
->var
.yres
,
1804 info
->var
.bits_per_pixel
);
1806 /* deferred io mode: disable clock to save power */
1807 if (info
->fbdefio
|| info
->state
== FBINFO_STATE_SUSPENDED
)
1808 sh_mobile_lcdc_clk_off(priv
);
1811 /* Failure ignored */
1812 priv
->notifier
.notifier_call
= sh_mobile_lcdc_notify
;
1813 fb_register_client(&priv
->notifier
);
1817 sh_mobile_lcdc_remove(pdev
);
1822 static struct platform_driver sh_mobile_lcdc_driver
= {
1824 .name
= "sh_mobile_lcdc_fb",
1825 .owner
= THIS_MODULE
,
1826 .pm
= &sh_mobile_lcdc_dev_pm_ops
,
1828 .probe
= sh_mobile_lcdc_probe
,
1829 .remove
= sh_mobile_lcdc_remove
,
1832 module_platform_driver(sh_mobile_lcdc_driver
);
1834 MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
1835 MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
1836 MODULE_LICENSE("GPL v2");