aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2011-08-30 16:02:02 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2011-08-30 16:02:02 -0400
commit8edbeb6eea647c26da482bd268ff67da209cba81 (patch)
tree251e607854abb6f8e7d82838ff3d7fd36586cc27
parentd4a7dbfdf180a656de3eb9e64614e2b991ffaa53 (diff)
parent8a20974f0370fe1b924704399e7ba327d894ef72 (diff)
Merge branch 'sh-mobile-lcdc' of git://linuxtv.org/pinchartl/fbdev into fbdev-next
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c1
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c592
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h12
-rw-r--r--drivers/video/sh_mobile_meram.c202
-rw-r--r--drivers/video/sh_mobile_meram.h41
-rw-r--r--include/video/sh_mobile_lcdc.h135
6 files changed, 556 insertions, 427 deletions
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index d41c01f83f15..6e3c2dfdcb81 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1583,6 +1583,7 @@ static void __init mackerel_init(void)
1583 1583
1584 sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); 1584 sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
1585 sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device); 1585 sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device);
1586 sh7372_add_device_to_domain(&sh7372_a4lc, &meram_device);
1586 sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); 1587 sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
1587 1588
1588 hdmi_init_pm_clock(); 1589 hdmi_init_pm_clock();
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index b048417247e8..088cb17857e3 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -24,39 +24,14 @@
24#include <linux/backlight.h> 24#include <linux/backlight.h>
25#include <linux/gpio.h> 25#include <linux/gpio.h>
26#include <video/sh_mobile_lcdc.h> 26#include <video/sh_mobile_lcdc.h>
27#include <video/sh_mobile_meram.h>
27#include <linux/atomic.h> 28#include <linux/atomic.h>
28 29
29#include "sh_mobile_lcdcfb.h" 30#include "sh_mobile_lcdcfb.h"
30#include "sh_mobile_meram.h"
31 31
32#define SIDE_B_OFFSET 0x1000 32#define SIDE_B_OFFSET 0x1000
33#define MIRROR_OFFSET 0x2000 33#define MIRROR_OFFSET 0x2000
34 34
35/* shared registers */
36#define _LDDCKR 0x410
37#define _LDDCKSTPR 0x414
38#define _LDINTR 0x468
39#define _LDSR 0x46c
40#define _LDCNT1R 0x470
41#define _LDCNT2R 0x474
42#define _LDRCNTR 0x478
43#define _LDDDSR 0x47c
44#define _LDDWD0R 0x800
45#define _LDDRDR 0x840
46#define _LDDWAR 0x900
47#define _LDDRAR 0x904
48
49/* shared registers and their order for context save/restore */
50static int lcdc_shared_regs[] = {
51 _LDDCKR,
52 _LDDCKSTPR,
53 _LDINTR,
54 _LDDDSR,
55 _LDCNT1R,
56 _LDCNT2R,
57};
58#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
59
60#define MAX_XRES 1920 35#define MAX_XRES 1920
61#define MAX_YRES 1080 36#define MAX_YRES 1080
62 37
@@ -98,22 +73,6 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
98 [LDPMR] = 0x63c, 73 [LDPMR] = 0x63c,
99}; 74};
100 75
101#define START_LCDC 0x00000001
102#define LCDC_RESET 0x00000100
103#define DISPLAY_BEU 0x00000008
104#define LCDC_ENABLE 0x00000001
105#define LDINTR_FE 0x00000400
106#define LDINTR_VSE 0x00000200
107#define LDINTR_VEE 0x00000100
108#define LDINTR_FS 0x00000004
109#define LDINTR_VSS 0x00000002
110#define LDINTR_VES 0x00000001
111#define LDRCNTR_SRS 0x00020000
112#define LDRCNTR_SRC 0x00010000
113#define LDRCNTR_MRS 0x00000002
114#define LDRCNTR_MRC 0x00000001
115#define LDSR_MRS 0x00000100
116
117static const struct fb_videomode default_720p = { 76static const struct fb_videomode default_720p = {
118 .name = "HDMI 720p", 77 .name = "HDMI 720p",
119 .xres = 1280, 78 .xres = 1280,
@@ -141,7 +100,6 @@ struct sh_mobile_lcdc_priv {
141 unsigned long lddckr; 100 unsigned long lddckr;
142 struct sh_mobile_lcdc_chan ch[2]; 101 struct sh_mobile_lcdc_chan ch[2];
143 struct notifier_block notifier; 102 struct notifier_block notifier;
144 unsigned long saved_shared_regs[NR_SHARED_REGS];
145 int started; 103 int started;
146 int forced_bpp; /* 2 channel LCDC must share bpp setting */ 104 int forced_bpp; /* 2 channel LCDC must share bpp setting */
147 struct sh_mobile_meram_info *meram_dev; 105 struct sh_mobile_meram_info *meram_dev;
@@ -218,33 +176,36 @@ static void lcdc_sys_write_index(void *handle, unsigned long data)
218{ 176{
219 struct sh_mobile_lcdc_chan *ch = handle; 177 struct sh_mobile_lcdc_chan *ch = handle;
220 178
221 lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000); 179 lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT);
222 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 180 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
223 lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 181 lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
224 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 182 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
183 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
225} 184}
226 185
227static void lcdc_sys_write_data(void *handle, unsigned long data) 186static void lcdc_sys_write_data(void *handle, unsigned long data)
228{ 187{
229 struct sh_mobile_lcdc_chan *ch = handle; 188 struct sh_mobile_lcdc_chan *ch = handle;
230 189
231 lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000); 190 lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW);
232 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 191 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
233 lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 192 lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
234 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 193 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
194 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
235} 195}
236 196
237static unsigned long lcdc_sys_read_data(void *handle) 197static unsigned long lcdc_sys_read_data(void *handle)
238{ 198{
239 struct sh_mobile_lcdc_chan *ch = handle; 199 struct sh_mobile_lcdc_chan *ch = handle;
240 200
241 lcdc_write(ch->lcdc, _LDDRDR, 0x01000000); 201 lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR);
242 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 202 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
243 lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 203 lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA |
204 (lcdc_chan_is_sublcd(ch) ? 2 : 0));
244 udelay(1); 205 udelay(1);
245 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 206 lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
246 207
247 return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff; 208 return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
248} 209}
249 210
250struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { 211struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
@@ -256,18 +217,22 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
256static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) 217static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
257{ 218{
258 if (atomic_inc_and_test(&priv->hw_usecnt)) { 219 if (atomic_inc_and_test(&priv->hw_usecnt)) {
259 pm_runtime_get_sync(priv->dev);
260 if (priv->dot_clk) 220 if (priv->dot_clk)
261 clk_enable(priv->dot_clk); 221 clk_enable(priv->dot_clk);
222 pm_runtime_get_sync(priv->dev);
223 if (priv->meram_dev && priv->meram_dev->pdev)
224 pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
262 } 225 }
263} 226}
264 227
265static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) 228static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
266{ 229{
267 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) { 230 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
231 if (priv->meram_dev && priv->meram_dev->pdev)
232 pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
233 pm_runtime_put(priv->dev);
268 if (priv->dot_clk) 234 if (priv->dot_clk)
269 clk_disable(priv->dot_clk); 235 clk_disable(priv->dot_clk);
270 pm_runtime_put(priv->dev);
271 } 236 }
272} 237}
273 238
@@ -319,13 +284,13 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
319 if (bcfg->start_transfer) 284 if (bcfg->start_transfer)
320 bcfg->start_transfer(bcfg->board_data, ch, 285 bcfg->start_transfer(bcfg->board_data, ch,
321 &sh_mobile_lcdc_sys_bus_ops); 286 &sh_mobile_lcdc_sys_bus_ops);
322 lcdc_write_chan(ch, LDSM2R, 1); 287 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
323 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 288 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
324 } else { 289 } else {
325 if (bcfg->start_transfer) 290 if (bcfg->start_transfer)
326 bcfg->start_transfer(bcfg->board_data, ch, 291 bcfg->start_transfer(bcfg->board_data, ch,
327 &sh_mobile_lcdc_sys_bus_ops); 292 &sh_mobile_lcdc_sys_bus_ops);
328 lcdc_write_chan(ch, LDSM2R, 1); 293 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
329 } 294 }
330} 295}
331 296
@@ -341,22 +306,16 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
341{ 306{
342 struct sh_mobile_lcdc_priv *priv = data; 307 struct sh_mobile_lcdc_priv *priv = data;
343 struct sh_mobile_lcdc_chan *ch; 308 struct sh_mobile_lcdc_chan *ch;
344 unsigned long tmp;
345 unsigned long ldintr; 309 unsigned long ldintr;
346 int is_sub; 310 int is_sub;
347 int k; 311 int k;
348 312
349 /* acknowledge interrupt */ 313 /* Acknowledge interrupts and disable further VSYNC End IRQs. */
350 ldintr = tmp = lcdc_read(priv, _LDINTR); 314 ldintr = lcdc_read(priv, _LDINTR);
351 /* 315 lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE);
352 * disable further VSYNC End IRQs, preserve all other enabled IRQs,
353 * write 0 to bits 0-6 to ack all triggered IRQs.
354 */
355 tmp &= 0xffffff00 & ~LDINTR_VEE;
356 lcdc_write(priv, _LDINTR, tmp);
357 316
358 /* figure out if this interrupt is for main or sub lcd */ 317 /* figure out if this interrupt is for main or sub lcd */
359 is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0; 318 is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0;
360 319
361 /* wake up channel and disable clocks */ 320 /* wake up channel and disable clocks */
362 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 321 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
@@ -365,7 +324,7 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
365 if (!ch->enabled) 324 if (!ch->enabled)
366 continue; 325 continue;
367 326
368 /* Frame Start */ 327 /* Frame End */
369 if (ldintr & LDINTR_FS) { 328 if (ldintr & LDINTR_FS) {
370 if (is_sub == lcdc_chan_is_sublcd(ch)) { 329 if (is_sub == lcdc_chan_is_sublcd(ch)) {
371 ch->frame_end = 1; 330 ch->frame_end = 1;
@@ -391,16 +350,17 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
391 350
392 /* start or stop the lcdc */ 351 /* start or stop the lcdc */
393 if (start) 352 if (start)
394 lcdc_write(priv, _LDCNT2R, tmp | START_LCDC); 353 lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO);
395 else 354 else
396 lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC); 355 lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO);
397 356
398 /* wait until power is applied/stopped on all channels */ 357 /* wait until power is applied/stopped on all channels */
399 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) 358 for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
400 if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled) 359 if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
401 while (1) { 360 while (1) {
402 tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3; 361 tmp = lcdc_read_chan(&priv->ch[k], LDPMR)
403 if (start && tmp == 3) 362 & LDPMR_LPS;
363 if (start && tmp == LDPMR_LPS)
404 break; 364 break;
405 if (!start && tmp == 0) 365 if (!start && tmp == 0)
406 break; 366 break;
@@ -418,13 +378,13 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
418 u32 tmp; 378 u32 tmp;
419 379
420 tmp = ch->ldmt1r_value; 380 tmp = ch->ldmt1r_value;
421 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28; 381 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL;
422 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27; 382 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL;
423 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0; 383 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0;
424 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0; 384 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0;
425 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0; 385 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0;
426 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0; 386 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0;
427 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0; 387 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0;
428 lcdc_write_chan(ch, LDMT1R, tmp); 388 lcdc_write_chan(ch, LDMT1R, tmp);
429 389
430 /* setup SYS bus */ 390 /* setup SYS bus */
@@ -463,242 +423,239 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
463 lcdc_write_chan(ch, LDHAJR, tmp); 423 lcdc_write_chan(ch, LDHAJR, tmp);
464} 424}
465 425
466static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 426/*
427 * __sh_mobile_lcdc_start - Configure and tart the LCDC
428 * @priv: LCDC device
429 *
430 * Configure all enabled channels and start the LCDC device. All external
431 * devices (clocks, MERAM, panels, ...) are not touched by this function.
432 */
433static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
467{ 434{
468 struct sh_mobile_lcdc_chan *ch; 435 struct sh_mobile_lcdc_chan *ch;
469 struct sh_mobile_lcdc_board_cfg *board_cfg;
470 unsigned long tmp; 436 unsigned long tmp;
471 int bpp = 0; 437 int bpp = 0;
472 unsigned long ldddsr; 438 int k, m;
473 int k, m, ret;
474
475 /* enable clocks before accessing the hardware */
476 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
477 if (priv->ch[k].enabled) {
478 sh_mobile_lcdc_clk_on(priv);
479 if (!bpp)
480 bpp = priv->ch[k].info->var.bits_per_pixel;
481 }
482 }
483
484 /* reset */
485 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
486 lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0);
487
488 /* enable LCDC channels */
489 tmp = lcdc_read(priv, _LDCNT2R);
490 tmp |= priv->ch[0].enabled;
491 tmp |= priv->ch[1].enabled;
492 lcdc_write(priv, _LDCNT2R, tmp);
493 439
494 /* read data from external memory, avoid using the BEU for now */ 440 /* Enable LCDC channels. Read data from external memory, avoid using the
495 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU); 441 * BEU for now.
442 */
443 lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled);
496 444
497 /* stop the lcdc first */ 445 /* Stop the LCDC first and disable all interrupts. */
498 sh_mobile_lcdc_start_stop(priv, 0); 446 sh_mobile_lcdc_start_stop(priv, 0);
447 lcdc_write(priv, _LDINTR, 0);
499 448
500 /* configure clocks */ 449 /* Configure power supply, dot clocks and start them. */
501 tmp = priv->lddckr; 450 tmp = priv->lddckr;
502 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 451 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
503 ch = &priv->ch[k]; 452 ch = &priv->ch[k];
504 453 if (!ch->enabled)
505 if (!priv->ch[k].enabled)
506 continue; 454 continue;
507 455
456 if (!bpp)
457 bpp = ch->info->var.bits_per_pixel;
458
459 /* Power supply */
460 lcdc_write_chan(ch, LDPMR, 0);
461
508 m = ch->cfg.clock_divider; 462 m = ch->cfg.clock_divider;
509 if (!m) 463 if (!m)
510 continue; 464 continue;
511 465
512 if (m == 1) 466 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
513 m = 1 << 6; 467 * denominator.
514 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); 468 */
515
516 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */
517 lcdc_write_chan(ch, LDDCKPAT1R, 0); 469 lcdc_write_chan(ch, LDDCKPAT1R, 0);
518 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); 470 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
471
472 if (m == 1)
473 m = LDDCKR_MOSEL;
474 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
519 } 475 }
520 476
521 lcdc_write(priv, _LDDCKR, tmp); 477 lcdc_write(priv, _LDDCKR, tmp);
522
523 /* start dotclock again */
524 lcdc_write(priv, _LDDCKSTPR, 0); 478 lcdc_write(priv, _LDDCKSTPR, 0);
525 lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0); 479 lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
526 480
527 /* interrupts are disabled to begin with */ 481 /* Setup geometry, format, frame buffer memory and operation mode. */
528 lcdc_write(priv, _LDINTR, 0);
529
530 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 482 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
531 ch = &priv->ch[k]; 483 ch = &priv->ch[k];
532
533 if (!ch->enabled) 484 if (!ch->enabled)
534 continue; 485 continue;
535 486
536 sh_mobile_lcdc_geometry(ch); 487 sh_mobile_lcdc_geometry(ch);
537 488
538 /* power supply */
539 lcdc_write_chan(ch, LDPMR, 0);
540
541 board_cfg = &ch->cfg.board_cfg;
542 if (board_cfg->setup_sys) {
543 ret = board_cfg->setup_sys(board_cfg->board_data,
544 ch, &sh_mobile_lcdc_sys_bus_ops);
545 if (ret)
546 return ret;
547 }
548 }
549
550 /* word and long word swap */
551 ldddsr = lcdc_read(priv, _LDDDSR);
552 if (priv->ch[0].info->var.nonstd)
553 lcdc_write(priv, _LDDDSR, ldddsr | 7);
554 else {
555 switch (bpp) {
556 case 16:
557 lcdc_write(priv, _LDDDSR, ldddsr | 6);
558 break;
559 case 24:
560 lcdc_write(priv, _LDDDSR, ldddsr | 7);
561 break;
562 case 32:
563 lcdc_write(priv, _LDDDSR, ldddsr | 4);
564 break;
565 }
566 }
567
568 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
569 unsigned long base_addr_y;
570 unsigned long base_addr_c = 0;
571 int pitch;
572 ch = &priv->ch[k];
573
574 if (!priv->ch[k].enabled)
575 continue;
576
577 /* set bpp format in PKF[4:0] */
578 tmp = lcdc_read_chan(ch, LDDFR);
579 tmp &= ~0x0003031f;
580 if (ch->info->var.nonstd) { 489 if (ch->info->var.nonstd) {
581 tmp |= (ch->info->var.nonstd << 16); 490 tmp = (ch->info->var.nonstd << 16);
582 switch (ch->info->var.bits_per_pixel) { 491 switch (ch->info->var.bits_per_pixel) {
583 case 12: 492 case 12:
493 tmp |= LDDFR_YF_420;
584 break; 494 break;
585 case 16: 495 case 16:
586 tmp |= (0x1 << 8); 496 tmp |= LDDFR_YF_422;
587 break; 497 break;
588 case 24: 498 case 24:
589 tmp |= (0x2 << 8); 499 default:
500 tmp |= LDDFR_YF_444;
590 break; 501 break;
591 } 502 }
592 } else { 503 } else {
593 switch (ch->info->var.bits_per_pixel) { 504 switch (ch->info->var.bits_per_pixel) {
594 case 16: 505 case 16:
595 tmp |= 0x03; 506 tmp = LDDFR_PKF_RGB16;
596 break; 507 break;
597 case 24: 508 case 24:
598 tmp |= 0x0b; 509 tmp = LDDFR_PKF_RGB24;
599 break; 510 break;
600 case 32: 511 case 32:
512 default:
513 tmp = LDDFR_PKF_ARGB32;
601 break; 514 break;
602 } 515 }
603 } 516 }
517
604 lcdc_write_chan(ch, LDDFR, tmp); 518 lcdc_write_chan(ch, LDDFR, tmp);
519 lcdc_write_chan(ch, LDMLSR, ch->pitch);
520 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
521 if (ch->info->var.nonstd)
522 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
605 523
606 base_addr_y = ch->info->fix.smem_start; 524 /* When using deferred I/O mode, configure the LCDC for one-shot
607 base_addr_c = base_addr_y + 525 * operation and enable the frame end interrupt. Otherwise use
608 ch->info->var.xres * 526 * continuous read mode.
609 ch->info->var.yres_virtual; 527 */
610 pitch = ch->info->fix.line_length; 528 if (ch->ldmt1r_value & LDMT1R_IFM &&
529 ch->cfg.sys_bus_cfg.deferred_io_msec) {
530 lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
531 lcdc_write(priv, _LDINTR, LDINTR_FE);
532 } else {
533 lcdc_write_chan(ch, LDSM1R, 0);
534 }
535 }
611 536
612 /* test if we can enable meram */ 537 /* Word and long word swap. */
613 if (ch->cfg.meram_cfg && priv->meram_dev && 538 if (priv->ch[0].info->var.nonstd)
614 priv->meram_dev->ops) { 539 tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
615 struct sh_mobile_meram_cfg *cfg; 540 else {
616 struct sh_mobile_meram_info *mdev; 541 switch (bpp) {
617 unsigned long icb_addr_y, icb_addr_c; 542 case 16:
618 int icb_pitch; 543 tmp = LDDDSR_LS | LDDDSR_WS;
619 int pf; 544 break;
545 case 24:
546 tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
547 break;
548 case 32:
549 default:
550 tmp = LDDDSR_LS;
551 break;
552 }
553 }
554 lcdc_write(priv, _LDDDSR, tmp);
620 555
621 cfg = ch->cfg.meram_cfg; 556 /* Enable the display output. */
622 mdev = priv->meram_dev; 557 lcdc_write(priv, _LDCNT1R, LDCNT1R_DE);
623 /* we need to de-init configured ICBs before we 558 sh_mobile_lcdc_start_stop(priv, 1);
624 * we can re-initialize them. 559 priv->started = 1;
625 */ 560}
626 if (ch->meram_enabled)
627 mdev->ops->meram_unregister(mdev, cfg);
628 561
629 ch->meram_enabled = 0; 562static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
563{
564 struct sh_mobile_meram_info *mdev = priv->meram_dev;
565 struct sh_mobile_lcdc_board_cfg *board_cfg;
566 struct sh_mobile_lcdc_chan *ch;
567 unsigned long tmp;
568 int ret;
569 int k;
630 570
631 if (ch->info->var.nonstd) { 571 /* enable clocks before accessing the hardware */
632 if (ch->info->var.bits_per_pixel == 24) 572 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
633 pf = SH_MOBILE_MERAM_PF_NV24; 573 if (priv->ch[k].enabled)
634 else 574 sh_mobile_lcdc_clk_on(priv);
635 pf = SH_MOBILE_MERAM_PF_NV; 575 }
636 } else {
637 pf = SH_MOBILE_MERAM_PF_RGB;
638 }
639 576
640 ret = mdev->ops->meram_register(mdev, cfg, pitch, 577 /* reset */
641 ch->info->var.yres, 578 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR);
642 pf, 579 lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
643 base_addr_y,
644 base_addr_c,
645 &icb_addr_y,
646 &icb_addr_c,
647 &icb_pitch);
648 if (!ret) {
649 /* set LDSA1R value */
650 base_addr_y = icb_addr_y;
651 pitch = icb_pitch;
652
653 /* set LDSA2R value if required */
654 if (base_addr_c)
655 base_addr_c = icb_addr_c;
656
657 ch->meram_enabled = 1;
658 }
659 }
660 580
661 /* point out our frame buffer */ 581 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
662 lcdc_write_chan(ch, LDSA1R, base_addr_y); 582 ch = &priv->ch[k];
663 if (ch->info->var.nonstd)
664 lcdc_write_chan(ch, LDSA2R, base_addr_c);
665 583
666 /* set line size */ 584 if (!ch->enabled)
667 lcdc_write_chan(ch, LDMLSR, pitch); 585 continue;
668 586
669 /* setup deferred io if SYS bus */ 587 board_cfg = &ch->cfg.board_cfg;
670 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; 588 if (board_cfg->setup_sys) {
671 if (ch->ldmt1r_value & (1 << 12) && tmp) { 589 ret = board_cfg->setup_sys(board_cfg->board_data, ch,
672 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; 590 &sh_mobile_lcdc_sys_bus_ops);
673 ch->defio.delay = msecs_to_jiffies(tmp); 591 if (ret)
674 ch->info->fbdefio = &ch->defio; 592 return ret;
675 fb_deferred_io_init(ch->info); 593 }
594 }
676 595
677 /* one-shot mode */ 596 /* Compute frame buffer base address and pitch for each channel. */
678 lcdc_write_chan(ch, LDSM1R, 1); 597 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
598 struct sh_mobile_meram_cfg *cfg;
599 int pixelformat;
679 600
680 /* enable "Frame End Interrupt Enable" bit */ 601 ch = &priv->ch[k];
681 lcdc_write(priv, _LDINTR, LDINTR_FE); 602 if (!ch->enabled)
603 continue;
682 604
683 } else { 605 ch->base_addr_y = ch->info->fix.smem_start;
684 /* continuous read mode */ 606 ch->base_addr_c = ch->base_addr_y
685 lcdc_write_chan(ch, LDSM1R, 0); 607 + ch->info->var.xres
608 * ch->info->var.yres_virtual;
609 ch->pitch = ch->info->fix.line_length;
610
611 /* Enable MERAM if possible. */
612 cfg = ch->cfg.meram_cfg;
613 if (mdev == NULL || mdev->ops == NULL || cfg == NULL)
614 continue;
615
616 /* we need to de-init configured ICBs before we can
617 * re-initialize them.
618 */
619 if (ch->meram_enabled) {
620 mdev->ops->meram_unregister(mdev, cfg);
621 ch->meram_enabled = 0;
686 } 622 }
687 }
688 623
689 /* display output */ 624 if (!ch->info->var.nonstd)
690 lcdc_write(priv, _LDCNT1R, LCDC_ENABLE); 625 pixelformat = SH_MOBILE_MERAM_PF_RGB;
626 else if (ch->info->var.bits_per_pixel == 24)
627 pixelformat = SH_MOBILE_MERAM_PF_NV24;
628 else
629 pixelformat = SH_MOBILE_MERAM_PF_NV;
630
631 ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
632 ch->info->var.yres, pixelformat,
633 ch->base_addr_y, ch->base_addr_c,
634 &ch->base_addr_y, &ch->base_addr_c,
635 &ch->pitch);
636 if (!ret)
637 ch->meram_enabled = 1;
638 }
691 639
692 /* start the lcdc */ 640 /* Start the LCDC. */
693 sh_mobile_lcdc_start_stop(priv, 1); 641 __sh_mobile_lcdc_start(priv);
694 priv->started = 1;
695 642
696 /* tell the board code to enable the panel */ 643 /* Setup deferred I/O, tell the board code to enable the panels, and
644 * turn backlight on.
645 */
697 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 646 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
698 ch = &priv->ch[k]; 647 ch = &priv->ch[k];
699 if (!ch->enabled) 648 if (!ch->enabled)
700 continue; 649 continue;
701 650
651 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
652 if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
653 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
654 ch->defio.delay = msecs_to_jiffies(tmp);
655 ch->info->fbdefio = &ch->defio;
656 fb_deferred_io_init(ch->info);
657 }
658
702 board_cfg = &ch->cfg.board_cfg; 659 board_cfg = &ch->cfg.board_cfg;
703 if (board_cfg->display_on && try_module_get(board_cfg->owner)) { 660 if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
704 board_cfg->display_on(board_cfg->board_data, ch->info); 661 board_cfg->display_on(board_cfg->board_data, ch->info);
@@ -776,42 +733,42 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
776 733
777static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) 734static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
778{ 735{
779 int ifm, miftyp; 736 int interface_type = ch->cfg.interface_type;
780 737
781 switch (ch->cfg.interface_type) { 738 switch (interface_type) {
782 case RGB8: ifm = 0; miftyp = 0; break; 739 case RGB8:
783 case RGB9: ifm = 0; miftyp = 4; break; 740 case RGB9:
784 case RGB12A: ifm = 0; miftyp = 5; break; 741 case RGB12A:
785 case RGB12B: ifm = 0; miftyp = 6; break; 742 case RGB12B:
786 case RGB16: ifm = 0; miftyp = 7; break; 743 case RGB16:
787 case RGB18: ifm = 0; miftyp = 10; break; 744 case RGB18:
788 case RGB24: ifm = 0; miftyp = 11; break; 745 case RGB24:
789 case SYS8A: ifm = 1; miftyp = 0; break; 746 case SYS8A:
790 case SYS8B: ifm = 1; miftyp = 1; break; 747 case SYS8B:
791 case SYS8C: ifm = 1; miftyp = 2; break; 748 case SYS8C:
792 case SYS8D: ifm = 1; miftyp = 3; break; 749 case SYS8D:
793 case SYS9: ifm = 1; miftyp = 4; break; 750 case SYS9:
794 case SYS12: ifm = 1; miftyp = 5; break; 751 case SYS12:
795 case SYS16A: ifm = 1; miftyp = 7; break; 752 case SYS16A:
796 case SYS16B: ifm = 1; miftyp = 8; break; 753 case SYS16B:
797 case SYS16C: ifm = 1; miftyp = 9; break; 754 case SYS16C:
798 case SYS18: ifm = 1; miftyp = 10; break; 755 case SYS18:
799 case SYS24: ifm = 1; miftyp = 11; break; 756 case SYS24:
800 default: goto bad; 757 break;
758 default:
759 return -EINVAL;
801 } 760 }
802 761
803 /* SUBLCD only supports SYS interface */ 762 /* SUBLCD only supports SYS interface */
804 if (lcdc_chan_is_sublcd(ch)) { 763 if (lcdc_chan_is_sublcd(ch)) {
805 if (ifm == 0) 764 if (!(interface_type & LDMT1R_IFM))
806 goto bad; 765 return -EINVAL;
807 else 766
808 ifm = 0; 767 interface_type &= ~LDMT1R_IFM;
809 } 768 }
810 769
811 ch->ldmt1r_value = (ifm << 12) | miftyp; 770 ch->ldmt1r_value = interface_type;
812 return 0; 771 return 0;
813 bad:
814 return -EINVAL;
815} 772}
816 773
817static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, 774static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
@@ -819,18 +776,24 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
819 struct sh_mobile_lcdc_priv *priv) 776 struct sh_mobile_lcdc_priv *priv)
820{ 777{
821 char *str; 778 char *str;
822 int icksel;
823 779
824 switch (clock_source) { 780 switch (clock_source) {
825 case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break; 781 case LCDC_CLK_BUS:
826 case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break; 782 str = "bus_clk";
827 case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break; 783 priv->lddckr = LDDCKR_ICKSEL_BUS;
784 break;
785 case LCDC_CLK_PERIPHERAL:
786 str = "peripheral_clk";
787 priv->lddckr = LDDCKR_ICKSEL_MIPI;
788 break;
789 case LCDC_CLK_EXTERNAL:
790 str = NULL;
791 priv->lddckr = LDDCKR_ICKSEL_HDMI;
792 break;
828 default: 793 default:
829 return -EINVAL; 794 return -EINVAL;
830 } 795 }
831 796
832 priv->lddckr = icksel << 16;
833
834 if (str) { 797 if (str) {
835 priv->dot_clk = clk_get(&pdev->dev, str); 798 priv->dot_clk = clk_get(&pdev->dev, str);
836 if (IS_ERR(priv->dot_clk)) { 799 if (IS_ERR(priv->dot_clk)) {
@@ -940,32 +903,28 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
940 base_addr_c += 2 * var->xoffset; 903 base_addr_c += 2 * var->xoffset;
941 else 904 else
942 base_addr_c += var->xoffset; 905 base_addr_c += var->xoffset;
943 } else 906 }
944 base_addr_c = 0;
945 907
946 if (!ch->meram_enabled) { 908 if (ch->meram_enabled) {
947 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
948 if (base_addr_c)
949 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
950 } else {
951 struct sh_mobile_meram_cfg *cfg; 909 struct sh_mobile_meram_cfg *cfg;
952 struct sh_mobile_meram_info *mdev; 910 struct sh_mobile_meram_info *mdev;
953 unsigned long icb_addr_y, icb_addr_c;
954 int ret; 911 int ret;
955 912
956 cfg = ch->cfg.meram_cfg; 913 cfg = ch->cfg.meram_cfg;
957 mdev = priv->meram_dev; 914 mdev = priv->meram_dev;
958 ret = mdev->ops->meram_update(mdev, cfg, 915 ret = mdev->ops->meram_update(mdev, cfg,
959 base_addr_y, base_addr_c, 916 base_addr_y, base_addr_c,
960 &icb_addr_y, &icb_addr_c); 917 &base_addr_y, &base_addr_c);
961 if (ret) 918 if (ret)
962 return ret; 919 return ret;
920 }
963 921
964 lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y); 922 ch->base_addr_y = base_addr_y;
965 if (icb_addr_c) 923 ch->base_addr_c = base_addr_c;
966 lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c);
967 924
968 } 925 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
926 if (var->nonstd)
927 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
969 928
970 if (lcdc_chan_is_sublcd(ch)) 929 if (lcdc_chan_is_sublcd(ch))
971 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); 930 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
@@ -985,9 +944,11 @@ static int sh_mobile_wait_for_vsync(struct fb_info *info)
985 unsigned long ldintr; 944 unsigned long ldintr;
986 int ret; 945 int ret;
987 946
988 /* Enable VSync End interrupt */ 947 /* Enable VSync End interrupt and be careful not to acknowledge any
948 * pending interrupt.
949 */
989 ldintr = lcdc_read(ch->lcdc, _LDINTR); 950 ldintr = lcdc_read(ch->lcdc, _LDINTR);
990 ldintr |= LDINTR_VEE; 951 ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
991 lcdc_write(ch->lcdc, _LDINTR, ldintr); 952 lcdc_write(ch->lcdc, _LDINTR, ldintr);
992 953
993 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion, 954 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
@@ -1316,47 +1277,20 @@ static int sh_mobile_lcdc_resume(struct device *dev)
1316static int sh_mobile_lcdc_runtime_suspend(struct device *dev) 1277static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
1317{ 1278{
1318 struct platform_device *pdev = to_platform_device(dev); 1279 struct platform_device *pdev = to_platform_device(dev);
1319 struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev); 1280 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
1320 struct sh_mobile_lcdc_chan *ch;
1321 int k, n;
1322
1323 /* save per-channel registers */
1324 for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
1325 ch = &p->ch[k];
1326 if (!ch->enabled)
1327 continue;
1328 for (n = 0; n < NR_CH_REGS; n++)
1329 ch->saved_ch_regs[n] = lcdc_read_chan(ch, n);
1330 }
1331
1332 /* save shared registers */
1333 for (n = 0; n < NR_SHARED_REGS; n++)
1334 p->saved_shared_regs[n] = lcdc_read(p, lcdc_shared_regs[n]);
1335 1281
1336 /* turn off LCDC hardware */ 1282 /* turn off LCDC hardware */
1337 lcdc_write(p, _LDCNT1R, 0); 1283 lcdc_write(priv, _LDCNT1R, 0);
1284
1338 return 0; 1285 return 0;
1339} 1286}
1340 1287
1341static int sh_mobile_lcdc_runtime_resume(struct device *dev) 1288static int sh_mobile_lcdc_runtime_resume(struct device *dev)
1342{ 1289{
1343 struct platform_device *pdev = to_platform_device(dev); 1290 struct platform_device *pdev = to_platform_device(dev);
1344 struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev); 1291 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
1345 struct sh_mobile_lcdc_chan *ch;
1346 int k, n;
1347
1348 /* restore per-channel registers */
1349 for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
1350 ch = &p->ch[k];
1351 if (!ch->enabled)
1352 continue;
1353 for (n = 0; n < NR_CH_REGS; n++)
1354 lcdc_write_chan(ch, n, ch->saved_ch_regs[n]);
1355 }
1356 1292
1357 /* restore shared registers */ 1293 __sh_mobile_lcdc_start(priv);
1358 for (n = 0; n < NR_SHARED_REGS; n++)
1359 lcdc_write(p, lcdc_shared_regs[n], p->saved_shared_regs[n]);
1360 1294
1361 return 0; 1295 return 0;
1362} 1296}
@@ -1472,12 +1406,12 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1472 1406
1473 switch (pdata->ch[i].chan) { 1407 switch (pdata->ch[i].chan) {
1474 case LCDC_CHAN_MAINLCD: 1408 case LCDC_CHAN_MAINLCD:
1475 ch->enabled = 1 << 1; 1409 ch->enabled = LDCNT2R_ME;
1476 ch->reg_offs = lcdc_offs_mainlcd; 1410 ch->reg_offs = lcdc_offs_mainlcd;
1477 j++; 1411 j++;
1478 break; 1412 break;
1479 case LCDC_CHAN_SUBLCD: 1413 case LCDC_CHAN_SUBLCD:
1480 ch->enabled = 1 << 2; 1414 ch->enabled = LDCNT2R_SE;
1481 ch->reg_offs = lcdc_offs_sublcd; 1415 ch->reg_offs = lcdc_offs_sublcd;
1482 j++; 1416 j++;
1483 break; 1417 break;
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index aeed6687e6a7..a58a0f38848b 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -18,6 +18,13 @@ struct sh_mobile_lcdc_priv;
18struct fb_info; 18struct fb_info;
19struct backlight_device; 19struct backlight_device;
20 20
21/*
22 * struct sh_mobile_lcdc_chan - LCDC display channel
23 *
24 * @base_addr_y: Frame buffer viewport base address (luma component)
25 * @base_addr_c: Frame buffer viewport base address (chroma component)
26 * @pitch: Frame buffer line pitch
27 */
21struct sh_mobile_lcdc_chan { 28struct sh_mobile_lcdc_chan {
22 struct sh_mobile_lcdc_priv *lcdc; 29 struct sh_mobile_lcdc_priv *lcdc;
23 unsigned long *reg_offs; 30 unsigned long *reg_offs;
@@ -25,7 +32,6 @@ struct sh_mobile_lcdc_chan {
25 unsigned long enabled; /* ME and SE in LDCNT2R */ 32 unsigned long enabled; /* ME and SE in LDCNT2R */
26 struct sh_mobile_lcdc_chan_cfg cfg; 33 struct sh_mobile_lcdc_chan_cfg cfg;
27 u32 pseudo_palette[PALETTE_NR]; 34 u32 pseudo_palette[PALETTE_NR];
28 unsigned long saved_ch_regs[NR_CH_REGS];
29 struct fb_info *info; 35 struct fb_info *info;
30 struct backlight_device *bl; 36 struct backlight_device *bl;
31 dma_addr_t dma_handle; 37 dma_addr_t dma_handle;
@@ -40,6 +46,10 @@ struct sh_mobile_lcdc_chan {
40 int blank_status; 46 int blank_status;
41 struct mutex open_lock; /* protects the use counter */ 47 struct mutex open_lock; /* protects the use counter */
42 int meram_enabled; 48 int meram_enabled;
49
50 unsigned long base_addr_y;
51 unsigned long base_addr_c;
52 unsigned int pitch;
43}; 53};
44 54
45#endif 55#endif
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index cc7d7329dc15..f63297099193 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -12,29 +12,103 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/device.h> 14#include <linux/device.h>
15#include <linux/pm_runtime.h>
15#include <linux/io.h> 16#include <linux/io.h>
16#include <linux/slab.h> 17#include <linux/slab.h>
17#include <linux/platform_device.h> 18#include <linux/platform_device.h>
18 19#include <video/sh_mobile_meram.h>
19#include "sh_mobile_meram.h"
20 20
21/* meram registers */ 21/* meram registers */
22#define MExxCTL 0x0 22#define MEVCR1 0x4
23#define MExxBSIZE 0x4 23#define MEVCR1_RST (1 << 31)
24#define MExxMNCF 0x8 24#define MEVCR1_WD (1 << 30)
25#define MExxSARA 0x10 25#define MEVCR1_AMD1 (1 << 29)
26#define MExxSARB 0x14 26#define MEVCR1_AMD0 (1 << 28)
27#define MExxSBSIZE 0x18 27#define MEQSEL1 0x40
28 28#define MEQSEL2 0x44
29#define MERAM_MExxCTL_VAL(ctl, next_icb, addr) \ 29
30 ((ctl) | (((next_icb) & 0x1f) << 11) | (((addr) & 0x7ff) << 16)) 30#define MExxCTL 0x400
31#define MERAM_MExxBSIZE_VAL(a, b, c) \ 31#define MExxCTL_BV (1 << 31)
32 (((a) << 28) | ((b) << 16) | (c)) 32#define MExxCTL_BSZ_SHIFT 28
33 33#define MExxCTL_MSAR_MASK (0x7ff << MExxCTL_MSAR_SHIFT)
34#define MEVCR1 0x4 34#define MExxCTL_MSAR_SHIFT 16
35#define MEACTS 0x10 35#define MExxCTL_NXT_MASK (0x1f << MExxCTL_NXT_SHIFT)
36#define MEQSEL1 0x40 36#define MExxCTL_NXT_SHIFT 11
37#define MEQSEL2 0x44 37#define MExxCTL_WD1 (1 << 10)
38#define MExxCTL_WD0 (1 << 9)
39#define MExxCTL_WS (1 << 8)
40#define MExxCTL_CB (1 << 7)
41#define MExxCTL_WBF (1 << 6)
42#define MExxCTL_WF (1 << 5)
43#define MExxCTL_RF (1 << 4)
44#define MExxCTL_CM (1 << 3)
45#define MExxCTL_MD_READ (1 << 0)
46#define MExxCTL_MD_WRITE (2 << 0)
47#define MExxCTL_MD_ICB_WB (3 << 0)
48#define MExxCTL_MD_ICB (4 << 0)
49#define MExxCTL_MD_FB (7 << 0)
50#define MExxCTL_MD_MASK (7 << 0)
51#define MExxBSIZE 0x404
52#define MExxBSIZE_RCNT_SHIFT 28
53#define MExxBSIZE_YSZM1_SHIFT 16
54#define MExxBSIZE_XSZM1_SHIFT 0
55#define MExxMNCF 0x408
56#define MExxMNCF_KWBNM_SHIFT 28
57#define MExxMNCF_KRBNM_SHIFT 24
58#define MExxMNCF_BNM_SHIFT 16
59#define MExxMNCF_XBV (1 << 15)
60#define MExxMNCF_CPL_YCBCR444 (1 << 12)
61#define MExxMNCF_CPL_YCBCR420 (2 << 12)
62#define MExxMNCF_CPL_YCBCR422 (3 << 12)
63#define MExxMNCF_CPL_MSK (3 << 12)
64#define MExxMNCF_BL (1 << 2)
65#define MExxMNCF_LNM_SHIFT 0
66#define MExxSARA 0x410
67#define MExxSARB 0x414
68#define MExxSBSIZE 0x418
69#define MExxSBSIZE_HDV (1 << 31)
70#define MExxSBSIZE_HSZ16 (0 << 28)
71#define MExxSBSIZE_HSZ32 (1 << 28)
72#define MExxSBSIZE_HSZ64 (2 << 28)
73#define MExxSBSIZE_HSZ128 (3 << 28)
74#define MExxSBSIZE_SBSIZZ_SHIFT 0
75
76#define MERAM_MExxCTL_VAL(next, addr) \
77 ((((next) << MExxCTL_NXT_SHIFT) & MExxCTL_NXT_MASK) | \
78 (((addr) << MExxCTL_MSAR_SHIFT) & MExxCTL_MSAR_MASK))
79#define MERAM_MExxBSIZE_VAL(rcnt, yszm1, xszm1) \
80 (((rcnt) << MExxBSIZE_RCNT_SHIFT) | \
81 ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \
82 ((xszm1) << MExxBSIZE_XSZM1_SHIFT))
83
84#define SH_MOBILE_MERAM_ICB_NUM 32
85
86static unsigned long common_regs[] = {
87 MEVCR1,
88 MEQSEL1,
89 MEQSEL2,
90};
91#define CMN_REGS_SIZE ARRAY_SIZE(common_regs)
92
93static unsigned long icb_regs[] = {
94 MExxCTL,
95 MExxBSIZE,
96 MExxMNCF,
97 MExxSARA,
98 MExxSARB,
99 MExxSBSIZE,
100};
101#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
102
103struct sh_mobile_meram_priv {
104 void __iomem *base;
105 struct mutex lock;
106 unsigned long used_icb;
107 int used_meram_cache_regions;
108 unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
109 unsigned long cmn_saved_regs[CMN_REGS_SIZE];
110 unsigned long icb_saved_regs[ICB_REGS_SIZE * SH_MOBILE_MERAM_ICB_NUM];
111};
38 112
39/* settings */ 113/* settings */
40#define MERAM_SEC_LINE 15 114#define MERAM_SEC_LINE 15
@@ -44,8 +118,7 @@
44 * MERAM/ICB access functions 118 * MERAM/ICB access functions
45 */ 119 */
46 120
47#define MERAM_ICB_OFFSET(base, idx, off) \ 121#define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20)
48 ((base) + (0x400 + ((idx) * 0x20) + (off)))
49 122
50static inline void meram_write_icb(void __iomem *base, int idx, int off, 123static inline void meram_write_icb(void __iomem *base, int idx, int off,
51 unsigned long val) 124 unsigned long val)
@@ -280,17 +353,18 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
280 /* 353 /*
281 * Set MERAM for framebuffer 354 * Set MERAM for framebuffer
282 * 355 *
283 * 0x70f: WD = 0x3, WS=0x1, CM=0x1, MD=FB mode
284 * we also chain the cache_icb and the marker_icb. 356 * we also chain the cache_icb and the marker_icb.
285 * we also split the allocated MERAM buffer between two ICBs. 357 * we also split the allocated MERAM buffer between two ICBs.
286 */ 358 */
287 meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 359 meram_write_icb(priv->base, icb->cache_icb, MExxCTL,
288 MERAM_MExxCTL_VAL(0x70f, icb->marker_icb, 360 MERAM_MExxCTL_VAL(icb->marker_icb, icb->meram_offset) |
289 icb->meram_offset)); 361 MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
362 MExxCTL_MD_FB);
290 meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 363 meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
291 MERAM_MExxCTL_VAL(0x70f, icb->cache_icb, 364 MERAM_MExxCTL_VAL(icb->cache_icb, icb->meram_offset +
292 icb->meram_offset + 365 icb->meram_size / 2) |
293 icb->meram_size / 2)); 366 MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
367 MExxCTL_MD_FB);
294 368
295 return 0; 369 return 0;
296} 370}
@@ -337,24 +411,22 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
337 xres, yres, (!pixelformat) ? "yuv" : "rgb", 411 xres, yres, (!pixelformat) ? "yuv" : "rgb",
338 base_addr_y, base_addr_c); 412 base_addr_y, base_addr_c);
339 413
340 mutex_lock(&priv->lock);
341
342 /* we can't handle wider than 8192px */ 414 /* we can't handle wider than 8192px */
343 if (xres > 8192) { 415 if (xres > 8192) {
344 dev_err(&pdev->dev, "width exceeding the limit (> 8192)."); 416 dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
345 error = -EINVAL; 417 return -EINVAL;
346 goto err;
347 }
348
349 if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
350 dev_err(&pdev->dev, "no more ICB available.");
351 error = -EINVAL;
352 goto err;
353 } 418 }
354 419
355 /* do we have at least one ICB config? */ 420 /* do we have at least one ICB config? */
356 if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) { 421 if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) {
357 dev_err(&pdev->dev, "at least one ICB is required."); 422 dev_err(&pdev->dev, "at least one ICB is required.");
423 return -EINVAL;
424 }
425
426 mutex_lock(&priv->lock);
427
428 if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
429 dev_err(&pdev->dev, "no more ICB available.");
358 error = -EINVAL; 430 error = -EINVAL;
359 goto err; 431 goto err;
360 } 432 }
@@ -460,6 +532,57 @@ static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata,
460 return 0; 532 return 0;
461} 533}
462 534
535static int sh_mobile_meram_runtime_suspend(struct device *dev)
536{
537 struct platform_device *pdev = to_platform_device(dev);
538 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
539 int k, j;
540
541 for (k = 0; k < CMN_REGS_SIZE; k++)
542 priv->cmn_saved_regs[k] = meram_read_reg(priv->base,
543 common_regs[k]);
544
545 for (j = 0; j < 32; j++) {
546 if (!test_bit(j, &priv->used_icb))
547 continue;
548 for (k = 0; k < ICB_REGS_SIZE; k++) {
549 priv->icb_saved_regs[j * ICB_REGS_SIZE + k] =
550 meram_read_icb(priv->base, j, icb_regs[k]);
551 /* Reset ICB on resume */
552 if (icb_regs[k] == MExxCTL)
553 priv->icb_saved_regs[j * ICB_REGS_SIZE + k] |=
554 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF;
555 }
556 }
557 return 0;
558}
559
560static int sh_mobile_meram_runtime_resume(struct device *dev)
561{
562 struct platform_device *pdev = to_platform_device(dev);
563 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
564 int k, j;
565
566 for (j = 0; j < 32; j++) {
567 if (!test_bit(j, &priv->used_icb))
568 continue;
569 for (k = 0; k < ICB_REGS_SIZE; k++) {
570 meram_write_icb(priv->base, j, icb_regs[k],
571 priv->icb_saved_regs[j * ICB_REGS_SIZE + k]);
572 }
573 }
574
575 for (k = 0; k < CMN_REGS_SIZE; k++)
576 meram_write_reg(priv->base, common_regs[k],
577 priv->cmn_saved_regs[k]);
578 return 0;
579}
580
581static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = {
582 .runtime_suspend = sh_mobile_meram_runtime_suspend,
583 .runtime_resume = sh_mobile_meram_runtime_resume,
584};
585
463static struct sh_mobile_meram_ops sh_mobile_meram_ops = { 586static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
464 .module = THIS_MODULE, 587 .module = THIS_MODULE,
465 .meram_register = sh_mobile_meram_register, 588 .meram_register = sh_mobile_meram_register,
@@ -513,7 +636,9 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
513 636
514 /* initialize ICB addressing mode */ 637 /* initialize ICB addressing mode */
515 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1) 638 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1)
516 meram_write_reg(priv->base, MEVCR1, 1 << 29); 639 meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1);
640
641 pm_runtime_enable(&pdev->dev);
517 642
518 dev_info(&pdev->dev, "sh_mobile_meram initialized."); 643 dev_info(&pdev->dev, "sh_mobile_meram initialized.");
519 644
@@ -530,6 +655,8 @@ static int sh_mobile_meram_remove(struct platform_device *pdev)
530{ 655{
531 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); 656 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
532 657
658 pm_runtime_disable(&pdev->dev);
659
533 if (priv->base) 660 if (priv->base)
534 iounmap(priv->base); 661 iounmap(priv->base);
535 662
@@ -544,6 +671,7 @@ static struct platform_driver sh_mobile_meram_driver = {
544 .driver = { 671 .driver = {
545 .name = "sh_mobile_meram", 672 .name = "sh_mobile_meram",
546 .owner = THIS_MODULE, 673 .owner = THIS_MODULE,
674 .pm = &sh_mobile_meram_dev_pm_ops,
547 }, 675 },
548 .probe = sh_mobile_meram_probe, 676 .probe = sh_mobile_meram_probe,
549 .remove = sh_mobile_meram_remove, 677 .remove = sh_mobile_meram_remove,
diff --git a/drivers/video/sh_mobile_meram.h b/drivers/video/sh_mobile_meram.h
deleted file mode 100644
index 82c54fbce8bd..000000000000
--- a/drivers/video/sh_mobile_meram.h
+++ /dev/null
@@ -1,41 +0,0 @@
1#ifndef __sh_mobile_meram_h__
2#define __sh_mobile_meram_h__
3
4#include <linux/mutex.h>
5#include <video/sh_mobile_meram.h>
6
7/*
8 * MERAM private
9 */
10
11#define MERAM_ICB_Y 0x1
12#define MERAM_ICB_C 0x2
13
14/* MERAM cache size */
15#define SH_MOBILE_MERAM_ICB_NUM 32
16
17#define SH_MOBILE_MERAM_CACHE_OFFSET(p) ((p) >> 16)
18#define SH_MOBILE_MERAM_CACHE_SIZE(p) ((p) & 0xffff)
19
20struct sh_mobile_meram_priv {
21 void __iomem *base;
22 struct mutex lock;
23 unsigned long used_icb;
24 int used_meram_cache_regions;
25 unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
26};
27
28int sh_mobile_meram_alloc_icb(const struct sh_mobile_meram_cfg *cfg,
29 int xres,
30 int yres,
31 unsigned int base_addr,
32 int yuv_mode,
33 int *marker_icb,
34 int *out_pitch);
35
36void sh_mobile_meram_free_icb(int marker_icb);
37
38#define SH_MOBILE_MERAM_START(ind, ab) \
39 (0xC0000000 | ((ab & 0x1) << 23) | ((ind & 0x1F) << 24))
40
41#endif /* !__sh_mobile_meram_h__ */
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index d964e68fc61d..8101b726b48a 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -4,26 +4,123 @@
4#include <linux/fb.h> 4#include <linux/fb.h>
5#include <video/sh_mobile_meram.h> 5#include <video/sh_mobile_meram.h>
6 6
7/* Register definitions */
8#define _LDDCKR 0x410
9#define LDDCKR_ICKSEL_BUS (0 << 16)
10#define LDDCKR_ICKSEL_MIPI (1 << 16)
11#define LDDCKR_ICKSEL_HDMI (2 << 16)
12#define LDDCKR_ICKSEL_EXT (3 << 16)
13#define LDDCKR_ICKSEL_MASK (7 << 16)
14#define LDDCKR_MOSEL (1 << 6)
15#define _LDDCKSTPR 0x414
16#define _LDINTR 0x468
17#define LDINTR_FE (1 << 10)
18#define LDINTR_VSE (1 << 9)
19#define LDINTR_VEE (1 << 8)
20#define LDINTR_FS (1 << 2)
21#define LDINTR_VSS (1 << 1)
22#define LDINTR_VES (1 << 0)
23#define LDINTR_STATUS_MASK (0xff << 0)
24#define _LDSR 0x46c
25#define LDSR_MSS (1 << 10)
26#define LDSR_MRS (1 << 8)
27#define LDSR_AS (1 << 1)
28#define _LDCNT1R 0x470
29#define LDCNT1R_DE (1 << 0)
30#define _LDCNT2R 0x474
31#define LDCNT2R_BR (1 << 8)
32#define LDCNT2R_MD (1 << 3)
33#define LDCNT2R_SE (1 << 2)
34#define LDCNT2R_ME (1 << 1)
35#define LDCNT2R_DO (1 << 0)
36#define _LDRCNTR 0x478
37#define LDRCNTR_SRS (1 << 17)
38#define LDRCNTR_SRC (1 << 16)
39#define LDRCNTR_MRS (1 << 1)
40#define LDRCNTR_MRC (1 << 0)
41#define _LDDDSR 0x47c
42#define LDDDSR_LS (1 << 2)
43#define LDDDSR_WS (1 << 1)
44#define LDDDSR_BS (1 << 0)
45
46#define LDMT1R_VPOL (1 << 28)
47#define LDMT1R_HPOL (1 << 27)
48#define LDMT1R_DWPOL (1 << 26)
49#define LDMT1R_DIPOL (1 << 25)
50#define LDMT1R_DAPOL (1 << 24)
51#define LDMT1R_HSCNT (1 << 17)
52#define LDMT1R_DWCNT (1 << 16)
53#define LDMT1R_IFM (1 << 12)
54#define LDMT1R_MIFTYP_RGB8 (0x0 << 0)
55#define LDMT1R_MIFTYP_RGB9 (0x4 << 0)
56#define LDMT1R_MIFTYP_RGB12A (0x5 << 0)
57#define LDMT1R_MIFTYP_RGB12B (0x6 << 0)
58#define LDMT1R_MIFTYP_RGB16 (0x7 << 0)
59#define LDMT1R_MIFTYP_RGB18 (0xa << 0)
60#define LDMT1R_MIFTYP_RGB24 (0xb << 0)
61#define LDMT1R_MIFTYP_YCBCR (0xf << 0)
62#define LDMT1R_MIFTYP_SYS8A (0x0 << 0)
63#define LDMT1R_MIFTYP_SYS8B (0x1 << 0)
64#define LDMT1R_MIFTYP_SYS8C (0x2 << 0)
65#define LDMT1R_MIFTYP_SYS8D (0x3 << 0)
66#define LDMT1R_MIFTYP_SYS9 (0x4 << 0)
67#define LDMT1R_MIFTYP_SYS12 (0x5 << 0)
68#define LDMT1R_MIFTYP_SYS16A (0x7 << 0)
69#define LDMT1R_MIFTYP_SYS16B (0x8 << 0)
70#define LDMT1R_MIFTYP_SYS16C (0x9 << 0)
71#define LDMT1R_MIFTYP_SYS18 (0xa << 0)
72#define LDMT1R_MIFTYP_SYS24 (0xb << 0)
73#define LDMT1R_MIFTYP_MASK (0xf << 0)
74
75#define LDDFR_CF1 (1 << 18)
76#define LDDFR_CF0 (1 << 17)
77#define LDDFR_CC (1 << 16)
78#define LDDFR_YF_420 (0 << 8)
79#define LDDFR_YF_422 (1 << 8)
80#define LDDFR_YF_444 (2 << 8)
81#define LDDFR_YF_MASK (3 << 8)
82#define LDDFR_PKF_ARGB32 (0x00 << 0)
83#define LDDFR_PKF_RGB16 (0x03 << 0)
84#define LDDFR_PKF_RGB24 (0x0b << 0)
85#define LDDFR_PKF_MASK (0x1f << 0)
86
87#define LDSM1R_OS (1 << 0)
88
89#define LDSM2R_OSTRG (1 << 0)
90
91#define LDPMR_LPS (3 << 0)
92
93#define _LDDWD0R 0x800
94#define LDDWDxR_WDACT (1 << 28)
95#define LDDWDxR_RSW (1 << 24)
96#define _LDDRDR 0x840
97#define LDDRDR_RSR (1 << 24)
98#define LDDRDR_DRD_MASK (0x3ffff << 0)
99#define _LDDWAR 0x900
100#define LDDWAR_WA (1 << 0)
101#define _LDDRAR 0x904
102#define LDDRAR_RA (1 << 0)
103
7enum { 104enum {
8 RGB8, /* 24bpp, 8:8:8 */ 105 RGB8 = LDMT1R_MIFTYP_RGB8, /* 24bpp, 8:8:8 */
9 RGB9, /* 18bpp, 9:9 */ 106 RGB9 = LDMT1R_MIFTYP_RGB9, /* 18bpp, 9:9 */
10 RGB12A, /* 24bpp, 12:12 */ 107 RGB12A = LDMT1R_MIFTYP_RGB12A, /* 24bpp, 12:12 */
11 RGB12B, /* 12bpp */ 108 RGB12B = LDMT1R_MIFTYP_RGB12B, /* 12bpp */
12 RGB16, /* 16bpp */ 109 RGB16 = LDMT1R_MIFTYP_RGB16, /* 16bpp */
13 RGB18, /* 18bpp */ 110 RGB18 = LDMT1R_MIFTYP_RGB18, /* 18bpp */
14 RGB24, /* 24bpp */ 111 RGB24 = LDMT1R_MIFTYP_RGB24, /* 24bpp */
15 YUV422, /* 16bpp */ 112 YUV422 = LDMT1R_MIFTYP_YCBCR, /* 16bpp */
16 SYS8A, /* 24bpp, 8:8:8 */ 113 SYS8A = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8A, /* 24bpp, 8:8:8 */
17 SYS8B, /* 18bpp, 8:8:2 */ 114 SYS8B = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8B, /* 18bpp, 8:8:2 */
18 SYS8C, /* 18bpp, 2:8:8 */ 115 SYS8C = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8C, /* 18bpp, 2:8:8 */
19 SYS8D, /* 16bpp, 8:8 */ 116 SYS8D = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8D, /* 16bpp, 8:8 */
20 SYS9, /* 18bpp, 9:9 */ 117 SYS9 = LDMT1R_IFM | LDMT1R_MIFTYP_SYS9, /* 18bpp, 9:9 */
21 SYS12, /* 24bpp, 12:12 */ 118 SYS12 = LDMT1R_IFM | LDMT1R_MIFTYP_SYS12, /* 24bpp, 12:12 */
22 SYS16A, /* 16bpp */ 119 SYS16A = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16A, /* 16bpp */
23 SYS16B, /* 18bpp, 16:2 */ 120 SYS16B = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16B, /* 18bpp, 16:2 */
24 SYS16C, /* 18bpp, 2:16 */ 121 SYS16C = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16C, /* 18bpp, 2:16 */
25 SYS18, /* 18bpp */ 122 SYS18 = LDMT1R_IFM | LDMT1R_MIFTYP_SYS18, /* 18bpp */
26 SYS24, /* 24bpp */ 123 SYS24 = LDMT1R_IFM | LDMT1R_MIFTYP_SYS24, /* 24bpp */
27}; 124};
28 125
29enum { LCDC_CHAN_DISABLED = 0, 126enum { LCDC_CHAN_DISABLED = 0,