aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/mx3fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/mx3fb.c')
-rw-r--r--drivers/video/mx3fb.c61
1 files changed, 22 insertions, 39 deletions
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index 1981e3665d07..727a5149d818 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -245,6 +245,7 @@ struct mx3fb_data {
245 245
246 uint32_t h_start_width; 246 uint32_t h_start_width;
247 uint32_t v_start_width; 247 uint32_t v_start_width;
248 enum disp_data_mapping disp_data_fmt;
248}; 249};
249 250
250struct dma_chan_request { 251struct dma_chan_request {
@@ -287,11 +288,14 @@ static void mx3fb_write_reg(struct mx3fb_data *mx3fb, u32 value, unsigned long r
287 __raw_writel(value, mx3fb->reg_base + reg); 288 __raw_writel(value, mx3fb->reg_base + reg);
288} 289}
289 290
290static const uint32_t di_mappings[] = { 291struct di_mapping {
291 0x1600AAAA, 0x00E05555, 0x00070000, 3, /* RGB888 */ 292 uint32_t b0, b1, b2;
292 0x0005000F, 0x000B000F, 0x0011000F, 1, /* RGB666 */ 293};
293 0x0011000F, 0x000B000F, 0x0005000F, 1, /* BGR666 */ 294
294 0x0004003F, 0x000A000F, 0x000F003F, 1 /* RGB565 */ 295static const struct di_mapping di_mappings[] = {
296 [IPU_DISP_DATA_MAPPING_RGB666] = { 0x0005000f, 0x000b000f, 0x0011000f },
297 [IPU_DISP_DATA_MAPPING_RGB565] = { 0x0004003f, 0x000a000f, 0x000f003f },
298 [IPU_DISP_DATA_MAPPING_RGB888] = { 0x00070000, 0x000f0000, 0x00170000 },
295}; 299};
296 300
297static void sdc_fb_init(struct mx3fb_info *fbi) 301static void sdc_fb_init(struct mx3fb_info *fbi)
@@ -425,7 +429,6 @@ static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel
425 * @pixel_clk: desired pixel clock frequency in Hz. 429 * @pixel_clk: desired pixel clock frequency in Hz.
426 * @width: width of panel in pixels. 430 * @width: width of panel in pixels.
427 * @height: height of panel in pixels. 431 * @height: height of panel in pixels.
428 * @pixel_fmt: pixel format of buffer as FOURCC ASCII code.
429 * @h_start_width: number of pixel clocks between the HSYNC signal pulse 432 * @h_start_width: number of pixel clocks between the HSYNC signal pulse
430 * and the start of valid data. 433 * and the start of valid data.
431 * @h_sync_width: width of the HSYNC signal in units of pixel clocks. 434 * @h_sync_width: width of the HSYNC signal in units of pixel clocks.
@@ -442,7 +445,6 @@ static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel
442static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel, 445static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
443 uint32_t pixel_clk, 446 uint32_t pixel_clk,
444 uint16_t width, uint16_t height, 447 uint16_t width, uint16_t height,
445 enum pixel_fmt pixel_fmt,
446 uint16_t h_start_width, uint16_t h_sync_width, 448 uint16_t h_start_width, uint16_t h_sync_width,
447 uint16_t h_end_width, uint16_t v_start_width, 449 uint16_t h_end_width, uint16_t v_start_width,
448 uint16_t v_sync_width, uint16_t v_end_width, 450 uint16_t v_sync_width, uint16_t v_end_width,
@@ -453,6 +455,7 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
453 uint32_t old_conf; 455 uint32_t old_conf;
454 uint32_t div; 456 uint32_t div;
455 struct clk *ipu_clk; 457 struct clk *ipu_clk;
458 const struct di_mapping *map;
456 459
457 dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height); 460 dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height);
458 461
@@ -540,36 +543,10 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
540 sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT; 543 sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT;
541 mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL); 544 mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL);
542 545
543 switch (pixel_fmt) { 546 map = &di_mappings[mx3fb->disp_data_fmt];
544 case IPU_PIX_FMT_RGB24: 547 mx3fb_write_reg(mx3fb, map->b0, DI_DISP3_B0_MAP);
545 mx3fb_write_reg(mx3fb, di_mappings[0], DI_DISP3_B0_MAP); 548 mx3fb_write_reg(mx3fb, map->b1, DI_DISP3_B1_MAP);
546 mx3fb_write_reg(mx3fb, di_mappings[1], DI_DISP3_B1_MAP); 549 mx3fb_write_reg(mx3fb, map->b2, DI_DISP3_B2_MAP);
547 mx3fb_write_reg(mx3fb, di_mappings[2], DI_DISP3_B2_MAP);
548 mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
549 ((di_mappings[3] - 1) << 12), DI_DISP_ACC_CC);
550 break;
551 case IPU_PIX_FMT_RGB666:
552 mx3fb_write_reg(mx3fb, di_mappings[4], DI_DISP3_B0_MAP);
553 mx3fb_write_reg(mx3fb, di_mappings[5], DI_DISP3_B1_MAP);
554 mx3fb_write_reg(mx3fb, di_mappings[6], DI_DISP3_B2_MAP);
555 mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
556 ((di_mappings[7] - 1) << 12), DI_DISP_ACC_CC);
557 break;
558 case IPU_PIX_FMT_BGR666:
559 mx3fb_write_reg(mx3fb, di_mappings[8], DI_DISP3_B0_MAP);
560 mx3fb_write_reg(mx3fb, di_mappings[9], DI_DISP3_B1_MAP);
561 mx3fb_write_reg(mx3fb, di_mappings[10], DI_DISP3_B2_MAP);
562 mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
563 ((di_mappings[11] - 1) << 12), DI_DISP_ACC_CC);
564 break;
565 default:
566 mx3fb_write_reg(mx3fb, di_mappings[12], DI_DISP3_B0_MAP);
567 mx3fb_write_reg(mx3fb, di_mappings[13], DI_DISP3_B1_MAP);
568 mx3fb_write_reg(mx3fb, di_mappings[14], DI_DISP3_B2_MAP);
569 mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
570 ((di_mappings[15] - 1) << 12), DI_DISP_ACC_CC);
571 break;
572 }
573 550
574 spin_unlock_irqrestore(&mx3fb->lock, lock_flags); 551 spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
575 552
@@ -780,8 +757,6 @@ static int __set_par(struct fb_info *fbi, bool lock)
780 if (sdc_init_panel(mx3fb, mode, 757 if (sdc_init_panel(mx3fb, mode,
781 (PICOS2KHZ(fbi->var.pixclock)) * 1000UL, 758 (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
782 fbi->var.xres, fbi->var.yres, 759 fbi->var.xres, fbi->var.yres,
783 (fbi->var.sync & FB_SYNC_SWAP_RGB) ?
784 IPU_PIX_FMT_BGR666 : IPU_PIX_FMT_RGB666,
785 fbi->var.left_margin, 760 fbi->var.left_margin,
786 fbi->var.hsync_len, 761 fbi->var.hsync_len,
787 fbi->var.right_margin + 762 fbi->var.right_margin +
@@ -1349,6 +1324,12 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
1349 const struct fb_videomode *mode; 1324 const struct fb_videomode *mode;
1350 int ret, num_modes; 1325 int ret, num_modes;
1351 1326
1327 if (mx3fb_pdata->disp_data_fmt >= ARRAY_SIZE(di_mappings)) {
1328 dev_err(dev, "Illegal display data format %d\n",
1329 mx3fb_pdata->disp_data_fmt);
1330 return -EINVAL;
1331 }
1332
1352 ichan->client = mx3fb; 1333 ichan->client = mx3fb;
1353 irq = ichan->eof_irq; 1334 irq = ichan->eof_irq;
1354 1335
@@ -1402,6 +1383,8 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
1402 mx3fbi->mx3fb = mx3fb; 1383 mx3fbi->mx3fb = mx3fb;
1403 mx3fbi->blank = FB_BLANK_NORMAL; 1384 mx3fbi->blank = FB_BLANK_NORMAL;
1404 1385
1386 mx3fb->disp_data_fmt = mx3fb_pdata->disp_data_fmt;
1387
1405 init_completion(&mx3fbi->flip_cmpl); 1388 init_completion(&mx3fbi->flip_cmpl);
1406 disable_irq(ichan->eof_irq); 1389 disable_irq(ichan->eof_irq);
1407 dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); 1390 dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq);