aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-30 11:26:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-30 11:26:25 -0400
commit706d4b12f8d7edd28d7e879a77235472da393edb (patch)
treec9bc1ce06b1154a49da1d0d907cac544a818eb0e /drivers/video
parent3af54c9bd9e6f14f896aac1bb0e8405ae0bc7a44 (diff)
parent9bafc74163d8bccca9810159aab39be926fb877c (diff)
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (215 commits) ARM: memblock: setup lowmem mappings using memblock ARM: memblock: move meminfo into find_limits directly ARM: memblock: convert free_highpages() to use memblock ARM: move freeing of highmem pages out of mem_init() ARM: memblock: convert memory detail printing to use memblock ARM: memblock: use memblock to free memory into arm_bootmem_init() ARM: memblock: use memblock when initializing memory allocators ARM: ensure membank array is always sorted ARM: 6466/1: implement flush_icache_all for the rest of the CPUs ARM: 6464/2: fix spinlock recursion in adjust_pte() ARM: fix memblock breakage ARM: 6465/1: Fix data abort accessing proc_info from __lookup_processor_type ARM: 6460/1: ixp2000: fix type of ixp2000_timer_interrupt ARM: 6449/1: Fix for compiler warning of uninitialized variable. ARM: 6445/1: fixup TCM memory types ARM: imx: Add wake functionality to GPIO ARM: mx5: Add gpio-keys to mx51 babbage board ARM: imx: Add gpio-keys to plat-mxc mx31_3ds: Fix spi registration mx31_3ds: Fix the logic for detecting the debug board ...
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/sh_mipi_dsi.c32
-rw-r--r--drivers/video/sh_mobile_hdmi.c629
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c348
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h41
4 files changed, 691 insertions, 359 deletions
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 5699ce0c1780..3f3d431033ca 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -123,83 +123,87 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
123 u32 linelength; 123 u32 linelength;
124 bool yuv; 124 bool yuv;
125 125
126 /* Select data format */ 126 /*
127 * Select data format. MIPI DSI is not hot-pluggable, so, we just use
128 * the default videomode. If this ever becomes a problem, We'll have to
129 * move this to mipi_display_on() above and use info->var.xres
130 */
127 switch (pdata->data_format) { 131 switch (pdata->data_format) {
128 case MIPI_RGB888: 132 case MIPI_RGB888:
129 pctype = 0; 133 pctype = 0;
130 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 134 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
131 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 135 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
132 linelength = ch->lcd_cfg.xres * 3; 136 linelength = ch->lcd_cfg[0].xres * 3;
133 yuv = false; 137 yuv = false;
134 break; 138 break;
135 case MIPI_RGB565: 139 case MIPI_RGB565:
136 pctype = 1; 140 pctype = 1;
137 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 141 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
138 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 142 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
139 linelength = ch->lcd_cfg.xres * 2; 143 linelength = ch->lcd_cfg[0].xres * 2;
140 yuv = false; 144 yuv = false;
141 break; 145 break;
142 case MIPI_RGB666_LP: 146 case MIPI_RGB666_LP:
143 pctype = 2; 147 pctype = 2;
144 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 148 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
145 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 149 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
146 linelength = ch->lcd_cfg.xres * 3; 150 linelength = ch->lcd_cfg[0].xres * 3;
147 yuv = false; 151 yuv = false;
148 break; 152 break;
149 case MIPI_RGB666: 153 case MIPI_RGB666:
150 pctype = 3; 154 pctype = 3;
151 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 155 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
152 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 156 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
153 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; 157 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8;
154 yuv = false; 158 yuv = false;
155 break; 159 break;
156 case MIPI_BGR888: 160 case MIPI_BGR888:
157 pctype = 8; 161 pctype = 8;
158 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 162 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
159 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 163 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
160 linelength = ch->lcd_cfg.xres * 3; 164 linelength = ch->lcd_cfg[0].xres * 3;
161 yuv = false; 165 yuv = false;
162 break; 166 break;
163 case MIPI_BGR565: 167 case MIPI_BGR565:
164 pctype = 9; 168 pctype = 9;
165 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 169 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
166 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 170 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
167 linelength = ch->lcd_cfg.xres * 2; 171 linelength = ch->lcd_cfg[0].xres * 2;
168 yuv = false; 172 yuv = false;
169 break; 173 break;
170 case MIPI_BGR666_LP: 174 case MIPI_BGR666_LP:
171 pctype = 0xa; 175 pctype = 0xa;
172 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 176 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
173 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 177 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
174 linelength = ch->lcd_cfg.xres * 3; 178 linelength = ch->lcd_cfg[0].xres * 3;
175 yuv = false; 179 yuv = false;
176 break; 180 break;
177 case MIPI_BGR666: 181 case MIPI_BGR666:
178 pctype = 0xb; 182 pctype = 0xb;
179 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 183 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
180 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 184 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
181 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; 185 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8;
182 yuv = false; 186 yuv = false;
183 break; 187 break;
184 case MIPI_YUYV: 188 case MIPI_YUYV:
185 pctype = 4; 189 pctype = 4;
186 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 190 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
187 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 191 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
188 linelength = ch->lcd_cfg.xres * 2; 192 linelength = ch->lcd_cfg[0].xres * 2;
189 yuv = true; 193 yuv = true;
190 break; 194 break;
191 case MIPI_UYVY: 195 case MIPI_UYVY:
192 pctype = 5; 196 pctype = 5;
193 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 197 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
194 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 198 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
195 linelength = ch->lcd_cfg.xres * 2; 199 linelength = ch->lcd_cfg[0].xres * 2;
196 yuv = true; 200 yuv = true;
197 break; 201 break;
198 case MIPI_YUV420_L: 202 case MIPI_YUV420_L:
199 pctype = 6; 203 pctype = 6;
200 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 204 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
201 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 205 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
202 linelength = (ch->lcd_cfg.xres * 12 + 7) / 8; 206 linelength = (ch->lcd_cfg[0].xres * 12 + 7) / 8;
203 yuv = true; 207 yuv = true;
204 break; 208 break;
205 case MIPI_YUV420: 209 case MIPI_YUV420:
@@ -207,7 +211,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
207 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 211 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
208 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 212 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
209 /* Length of U/V line */ 213 /* Length of U/V line */
210 linelength = (ch->lcd_cfg.xres + 1) / 2; 214 linelength = (ch->lcd_cfg[0].xres + 1) / 2;
211 yuv = true; 215 yuv = true;
212 break; 216 break;
213 default: 217 default:
@@ -281,7 +285,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
281 iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */ 285 iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */
282 /* 286 /*
283 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see 287 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
284 * sh_mobile_lcdc_info.ch[0].lcd_cfg.xres), HSALEN = 1 - default 288 * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default
285 * (unused, since VMCTR2[HSABM] = 0) 289 * (unused, since VMCTR2[HSABM] = 0)
286 */ 290 */
287 iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */ 291 iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index ef989d94511c..55b3077ff6ff 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -28,6 +28,8 @@
28#include <video/sh_mobile_hdmi.h> 28#include <video/sh_mobile_hdmi.h>
29#include <video/sh_mobile_lcdc.h> 29#include <video/sh_mobile_lcdc.h>
30 30
31#include "sh_mobile_lcdcfb.h"
32
31#define HDMI_SYSTEM_CTRL 0x00 /* System control */ 33#define HDMI_SYSTEM_CTRL 0x00 /* System control */
32#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, 34#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control,
33 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ 35 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
@@ -206,12 +208,15 @@ enum hotplug_state {
206 208
207struct sh_hdmi { 209struct sh_hdmi {
208 void __iomem *base; 210 void __iomem *base;
209 enum hotplug_state hp_state; 211 enum hotplug_state hp_state; /* hot-plug status */
212 bool preprogrammed_mode; /* use a pre-programmed VIC or the external mode */
210 struct clk *hdmi_clk; 213 struct clk *hdmi_clk;
211 struct device *dev; 214 struct device *dev;
212 struct fb_info *info; 215 struct fb_info *info;
216 struct mutex mutex; /* Protect the info pointer */
213 struct delayed_work edid_work; 217 struct delayed_work edid_work;
214 struct fb_var_screeninfo var; 218 struct fb_var_screeninfo var;
219 struct fb_monspecs monspec;
215}; 220};
216 221
217static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) 222static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
@@ -277,7 +282,7 @@ static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
277 */ 282 */
278 283
279/* External video parameter settings */ 284/* External video parameter settings */
280static void hdmi_external_video_param(struct sh_hdmi *hdmi) 285static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
281{ 286{
282 struct fb_var_screeninfo *var = &hdmi->var; 287 struct fb_var_screeninfo *var = &hdmi->var;
283 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset; 288 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
@@ -309,9 +314,9 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi)
309 if (var->sync & FB_SYNC_VERT_HIGH_ACT) 314 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
310 sync |= 8; 315 sync |= 8;
311 316
312 pr_debug("H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n", 317 dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
313 htotal, hblank, hdelay, var->hsync_len, 318 htotal, hblank, hdelay, var->hsync_len,
314 vtotal, vblank, vdelay, var->vsync_len, sync); 319 vtotal, vblank, vdelay, var->vsync_len, sync);
315 320
316 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); 321 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
317 322
@@ -336,7 +341,10 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi)
336 341
337 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); 342 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
338 343
339 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for manual mode */ 344 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
345 if (!hdmi->preprogrammed_mode)
346 hdmi_write(hdmi, sync | 1 | (voffset << 4),
347 HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
340} 348}
341 349
342/** 350/**
@@ -454,21 +462,61 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
454} 462}
455 463
456/** 464/**
457 * sh_hdmi_phy_config() 465 * sh_hdmi_phy_config() - configure the HDMI PHY for the used video mode
458 */ 466 */
459static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) 467static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
460{ 468{
461 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ 469 if (hdmi->var.yres > 480) {
462 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); 470 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
463 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); 471 /*
464 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); 472 * [1:0] Speed_A
465 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */ 473 * [3:2] Speed_B
466 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); 474 * [4] PLLA_Bypass
467 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); 475 * [6] DRV_TEST_EN
468 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); 476 * [7] DRV_TEST_IN
469 hdmi_write(hdmi, 0x0E, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); 477 */
470 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); 478 hdmi_write(hdmi, 0x0f, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
471 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); 479 /* PLLB_CONFIG[17], PLLA_CONFIG[17] - not in PHY datasheet */
480 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
481 /*
482 * [2:0] BGR_I_OFFSET
483 * [6:4] BGR_V_OFFSET
484 */
485 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
486 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */
487 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
488 /*
489 * PLLA_CONFIG[15:8]: regulator voltage[0], CP current,
490 * LPF capacitance, LPF resistance[1]
491 */
492 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
493 /* PLLB_CONFIG[7:0]: LPF resistance[0], VCO offset, VCO gain */
494 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
495 /*
496 * PLLB_CONFIG[15:8]: regulator voltage[0], CP current,
497 * LPF capacitance, LPF resistance[1]
498 */
499 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
500 /* DRV_CONFIG, PE_CONFIG */
501 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
502 /*
503 * [2:0] AMON_SEL (4 == LPF voltage)
504 * [4] PLLA_CONFIG[16]
505 * [5] PLLB_CONFIG[16]
506 */
507 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
508 } else {
509 /* for 480p8bit 27MHz */
510 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
511 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
512 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
513 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
514 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
515 hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
516 hdmi_write(hdmi, 0x0F, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
517 hdmi_write(hdmi, 0x20, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
518 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
519 }
472} 520}
473 521
474/** 522/**
@@ -476,6 +524,8 @@ static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
476 */ 524 */
477static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi) 525static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
478{ 526{
527 u8 vic;
528
479 /* AVI InfoFrame */ 529 /* AVI InfoFrame */
480 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX); 530 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX);
481 531
@@ -500,9 +550,9 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
500 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1); 550 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
501 551
502 /* 552 /*
503 * C = No Data 553 * [7:6] C = Colorimetry: no data
504 * M = 16:9 Picture Aspect Ratio 554 * [5:4] M = 2: 16:9, 1: 4:3 Picture Aspect Ratio
505 * R = Same as picture aspect ratio 555 * [3:0] R = 8: Active Frame Aspect Ratio: same as picture aspect ratio
506 */ 556 */
507 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2); 557 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
508 558
@@ -516,9 +566,15 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
516 566
517 /* 567 /*
518 * VIC = 1280 x 720p: ignored if external config is used 568 * VIC = 1280 x 720p: ignored if external config is used
519 * Send 2 for 720 x 480p, 16 for 1080p 569 * Send 2 for 720 x 480p, 16 for 1080p, ignored in external mode
520 */ 570 */
521 hdmi_write(hdmi, 4, HDMI_CTRL_PKT_BUF_ACCESS_PB4); 571 if (hdmi->var.yres == 1080 && hdmi->var.xres == 1920)
572 vic = 16;
573 else if (hdmi->var.yres == 480 && hdmi->var.xres == 720)
574 vic = 2;
575 else
576 vic = 4;
577 hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
522 578
523 /* PR = No Repetition */ 579 /* PR = No Repetition */
524 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5); 580 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
@@ -592,100 +648,6 @@ static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi)
592} 648}
593 649
594/** 650/**
595 * sh_hdmi_gamut_metadata_setup() - Gamut Metadata Packet of CONTROL PACKET
596 */
597static void sh_hdmi_gamut_metadata_setup(struct sh_hdmi *hdmi)
598{
599 int i;
600
601 /* Gamut Metadata Packet */
602 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_INDEX);
603
604 /* Packet Type = 0x0A */
605 hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
606 /* Gamut Packet is not used, so default value */
607 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
608 /* Gamut Packet is not used, so default value */
609 hdmi_write(hdmi, 0x10, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
610
611 /* GBD bytes 0 through 27 */
612 for (i = 0; i <= 27; i++)
613 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0_63H - PB27_7EH */
614 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
615}
616
617/**
618 * sh_hdmi_acp_setup() - Audio Content Protection Packet (ACP)
619 */
620static void sh_hdmi_acp_setup(struct sh_hdmi *hdmi)
621{
622 int i;
623
624 /* Audio Content Protection Packet (ACP) */
625 hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_INDEX);
626
627 /* Packet Type = 0x04 */
628 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
629 /* ACP_Type */
630 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
631 /* Reserved (0) */
632 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
633
634 /* GBD bytes 0 through 27 */
635 for (i = 0; i <= 27; i++)
636 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
637 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
638}
639
640/**
641 * sh_hdmi_isrc1_setup() - ISRC1 Packet
642 */
643static void sh_hdmi_isrc1_setup(struct sh_hdmi *hdmi)
644{
645 int i;
646
647 /* ISRC1 Packet */
648 hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_INDEX);
649
650 /* Packet Type = 0x05 */
651 hdmi_write(hdmi, 0x05, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
652 /* ISRC_Cont, ISRC_Valid, Reserved (0), ISRC_Status */
653 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
654 /* Reserved (0) */
655 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
656
657 /* PB0 UPC_EAN_ISRC_0-15 */
658 /* Bytes PB16-PB27 shall be set to a value of 0. */
659 for (i = 0; i <= 27; i++)
660 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
661 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
662}
663
664/**
665 * sh_hdmi_isrc2_setup() - ISRC2 Packet
666 */
667static void sh_hdmi_isrc2_setup(struct sh_hdmi *hdmi)
668{
669 int i;
670
671 /* ISRC2 Packet */
672 hdmi_write(hdmi, 0x03, HDMI_CTRL_PKT_BUF_INDEX);
673
674 /* HB0 Packet Type = 0x06 */
675 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
676 /* Reserved (0) */
677 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
678 /* Reserved (0) */
679 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
680
681 /* PB0 UPC_EAN_ISRC_16-31 */
682 /* Bytes PB16-PB27 shall be set to a value of 0. */
683 for (i = 0; i <= 27; i++)
684 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
685 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
686}
687
688/**
689 * sh_hdmi_configure() - Initialise HDMI for output 651 * sh_hdmi_configure() - Initialise HDMI for output
690 */ 652 */
691static void sh_hdmi_configure(struct sh_hdmi *hdmi) 653static void sh_hdmi_configure(struct sh_hdmi *hdmi)
@@ -705,18 +667,6 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
705 /* Audio InfoFrame */ 667 /* Audio InfoFrame */
706 sh_hdmi_audio_infoframe_setup(hdmi); 668 sh_hdmi_audio_infoframe_setup(hdmi);
707 669
708 /* Gamut Metadata packet */
709 sh_hdmi_gamut_metadata_setup(hdmi);
710
711 /* Audio Content Protection (ACP) Packet */
712 sh_hdmi_acp_setup(hdmi);
713
714 /* ISRC1 Packet */
715 sh_hdmi_isrc1_setup(hdmi);
716
717 /* ISRC2 Packet */
718 sh_hdmi_isrc2_setup(hdmi);
719
720 /* 670 /*
721 * Control packet auto send with VSYNC control: auto send 671 * Control packet auto send with VSYNC control: auto send
722 * General control, Gamut metadata, ISRC, and ACP packets 672 * General control, Gamut metadata, ISRC, and ACP packets
@@ -734,17 +684,42 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
734 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL); 684 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
735} 685}
736 686
737static void sh_hdmi_read_edid(struct sh_hdmi *hdmi) 687static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
688 const struct fb_videomode *mode)
738{ 689{
739 struct fb_var_screeninfo *var = &hdmi->var; 690 long target = PICOS2KHZ(mode->pixclock) * 1000,
740 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 691 rate = clk_round_rate(hdmi->hdmi_clk, target);
741 struct fb_videomode *lcd_cfg = &pdata->lcd_chan->lcd_cfg; 692 unsigned long rate_error = rate > 0 ? abs(rate - target) : ULONG_MAX;
742 unsigned long height = var->height, width = var->width; 693
743 int i; 694 dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
695 mode->left_margin, mode->xres,
696 mode->right_margin, mode->hsync_len,
697 mode->upper_margin, mode->yres,
698 mode->lower_margin, mode->vsync_len);
699
700 dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz\n", target,
701 rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
702 mode->refresh);
703
704 return rate_error;
705}
706
707static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
708{
709 struct fb_var_screeninfo tmpvar;
710 struct fb_var_screeninfo *var = &tmpvar;
711 const struct fb_videomode *mode, *found = NULL;
712 struct fb_info *info = hdmi->info;
713 struct fb_modelist *modelist = NULL;
714 unsigned int f_width = 0, f_height = 0, f_refresh = 0;
715 unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
716 bool exact_match = false;
744 u8 edid[128]; 717 u8 edid[128];
718 char *forced;
719 int i;
745 720
746 /* Read EDID */ 721 /* Read EDID */
747 pr_debug("Read back EDID code:"); 722 dev_dbg(hdmi->dev, "Read back EDID code:");
748 for (i = 0; i < 128; i++) { 723 for (i = 0; i < 128; i++) {
749 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); 724 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
750#ifdef DEBUG 725#ifdef DEBUG
@@ -759,29 +734,97 @@ static void sh_hdmi_read_edid(struct sh_hdmi *hdmi)
759#ifdef DEBUG 734#ifdef DEBUG
760 printk(KERN_CONT "\n"); 735 printk(KERN_CONT "\n");
761#endif 736#endif
762 fb_parse_edid(edid, var); 737
763 pr_debug("%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n", 738 fb_edid_to_monspecs(edid, &hdmi->monspec);
764 var->left_margin, var->xres, var->right_margin, var->hsync_len, 739
765 var->upper_margin, var->yres, var->lower_margin, var->vsync_len, 740 fb_get_options("sh_mobile_lcdc", &forced);
766 PICOS2KHZ(var->pixclock)); 741 if (forced && *forced) {
767 742 /* Only primitive parsing so far */
768 /* FIXME: Use user-provided configuration instead of EDID */ 743 i = sscanf(forced, "%ux%u@%u",
769 var->width = width; 744 &f_width, &f_height, &f_refresh);
770 var->xres = lcd_cfg->xres; 745 if (i < 2) {
771 var->xres_virtual = lcd_cfg->xres; 746 f_width = 0;
772 var->left_margin = lcd_cfg->left_margin; 747 f_height = 0;
773 var->right_margin = lcd_cfg->right_margin; 748 }
774 var->hsync_len = lcd_cfg->hsync_len; 749 dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n",
775 var->height = height; 750 f_width, f_height, f_refresh);
776 var->yres = lcd_cfg->yres; 751 }
777 var->yres_virtual = lcd_cfg->yres * 2; 752
778 var->upper_margin = lcd_cfg->upper_margin; 753 /* Walk monitor modes to find the best or the exact match */
779 var->lower_margin = lcd_cfg->lower_margin; 754 for (i = 0, mode = hdmi->monspec.modedb;
780 var->vsync_len = lcd_cfg->vsync_len; 755 f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match;
781 var->sync = lcd_cfg->sync; 756 i++, mode++) {
782 var->pixclock = lcd_cfg->pixclock; 757 unsigned long rate_error = sh_hdmi_rate_error(hdmi, mode);
783 758
784 hdmi_external_video_param(hdmi); 759 /* No interest in unmatching modes */
760 if (f_width != mode->xres || f_height != mode->yres)
761 continue;
762 if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
763 /*
764 * Exact match if either the refresh rate matches or it
765 * hasn't been specified and we've found a mode, for
766 * which we can configure the clock precisely
767 */
768 exact_match = true;
769 else if (found && found_rate_error <= rate_error)
770 /*
771 * We otherwise search for the closest matching clock
772 * rate - either if no refresh rate has been specified
773 * or we cannot find an exactly matching one
774 */
775 continue;
776
777 /* Check if supported: sufficient fb memory, supported clock-rate */
778 fb_videomode_to_var(var, mode);
779
780 if (info && info->fbops->fb_check_var &&
781 info->fbops->fb_check_var(var, info)) {
782 exact_match = false;
783 continue;
784 }
785
786 found = mode;
787 found_rate_error = rate_error;
788 }
789
790 /*
791 * TODO 1: if no ->info is present, postpone running the config until
792 * after ->info first gets registered.
793 * TODO 2: consider registering the HDMI platform device from the LCDC
794 * driver, and passing ->info with HDMI platform data.
795 */
796 if (info && !found) {
797 modelist = hdmi->info->modelist.next &&
798 !list_empty(&hdmi->info->modelist) ?
799 list_entry(hdmi->info->modelist.next,
800 struct fb_modelist, list) :
801 NULL;
802
803 if (modelist) {
804 found = &modelist->mode;
805 found_rate_error = sh_hdmi_rate_error(hdmi, found);
806 }
807 }
808
809 /* No cookie today */
810 if (!found)
811 return -ENXIO;
812
813 dev_info(hdmi->dev, "Using %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
814 modelist ? "default" : "EDID", found->xres, found->yres,
815 found->refresh, PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
816
817 if ((found->xres == 720 && found->yres == 480) ||
818 (found->xres == 1280 && found->yres == 720) ||
819 (found->xres == 1920 && found->yres == 1080))
820 hdmi->preprogrammed_mode = true;
821 else
822 hdmi->preprogrammed_mode = false;
823
824 fb_videomode_to_var(&hdmi->var, found);
825 sh_hdmi_external_video_param(hdmi);
826
827 return 0;
785} 828}
786 829
787static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) 830static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
@@ -809,8 +852,8 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
809 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2); 852 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2);
810 853
811 if (printk_ratelimit()) 854 if (printk_ratelimit())
812 pr_debug("IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n", 855 dev_dbg(hdmi->dev, "IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n",
813 irq, status1, mask1, status2, mask2); 856 irq, status1, mask1, status2, mask2);
814 857
815 if (!((status1 & mask1) | (status2 & mask2))) { 858 if (!((status1 & mask1) | (status2 & mask2))) {
816 return IRQ_NONE; 859 return IRQ_NONE;
@@ -821,7 +864,7 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
821 udelay(500); 864 udelay(500);
822 865
823 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS); 866 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS);
824 pr_debug("MSENS 0x%x\n", msens); 867 dev_dbg(hdmi->dev, "MSENS 0x%x\n", msens);
825 /* Check, if hot plug & MSENS pin status are both high */ 868 /* Check, if hot plug & MSENS pin status are both high */
826 if ((msens & 0xC0) == 0xC0) { 869 if ((msens & 0xC0) == 0xC0) {
827 /* Display plug in */ 870 /* Display plug in */
@@ -857,83 +900,176 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
857 return IRQ_HANDLED; 900 return IRQ_HANDLED;
858} 901}
859 902
860static void hdmi_display_on(void *arg, struct fb_info *info) 903/* locking: called with info->lock held, or before register_framebuffer() */
904static void sh_hdmi_display_on(void *arg, struct fb_info *info)
861{ 905{
906 /*
907 * info is guaranteed to be valid, when we are called, because our
908 * FB_EVENT_FB_UNBIND notify is also called with info->lock held
909 */
862 struct sh_hdmi *hdmi = arg; 910 struct sh_hdmi *hdmi = arg;
863 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 911 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
912 struct sh_mobile_lcdc_chan *ch = info->par;
864 913
865 if (info->var.xres != 1280 || info->var.yres != 720) { 914 dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__,
866 dev_warn(info->device, "Unsupported framebuffer geometry %ux%u\n", 915 pdata->lcd_dev, info->state);
867 info->var.xres, info->var.yres); 916
868 return; 917 /* No need to lock */
869 } 918 hdmi->info = info;
870 919
871 pr_debug("%s(%p): state %x\n", __func__, pdata->lcd_dev, info->state);
872 /* 920 /*
873 * FIXME: not a good place to store fb_info. And we cannot nullify it 921 * hp_state can be set to
874 * even on monitor disconnect. What should the lifecycle be? 922 * HDMI_HOTPLUG_DISCONNECTED: on monitor unplug
923 * HDMI_HOTPLUG_CONNECTED: on monitor plug-in
924 * HDMI_HOTPLUG_EDID_DONE: on EDID read completion
875 */ 925 */
876 hdmi->info = info;
877 switch (hdmi->hp_state) { 926 switch (hdmi->hp_state) {
878 case HDMI_HOTPLUG_EDID_DONE: 927 case HDMI_HOTPLUG_EDID_DONE:
879 /* PS mode d->e. All functions are active */ 928 /* PS mode d->e. All functions are active */
880 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); 929 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
881 pr_debug("HDMI running\n"); 930 dev_dbg(hdmi->dev, "HDMI running\n");
882 break; 931 break;
883 case HDMI_HOTPLUG_DISCONNECTED: 932 case HDMI_HOTPLUG_DISCONNECTED:
884 info->state = FBINFO_STATE_SUSPENDED; 933 info->state = FBINFO_STATE_SUSPENDED;
885 default: 934 default:
886 hdmi->var = info->var; 935 hdmi->var = ch->display_var;
887 } 936 }
888} 937}
889 938
890static void hdmi_display_off(void *arg) 939/* locking: called with info->lock held */
940static void sh_hdmi_display_off(void *arg)
891{ 941{
892 struct sh_hdmi *hdmi = arg; 942 struct sh_hdmi *hdmi = arg;
893 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 943 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
894 944
895 pr_debug("%s(%p)\n", __func__, pdata->lcd_dev); 945 dev_dbg(hdmi->dev, "%s(%p)\n", __func__, pdata->lcd_dev);
896 /* PS mode e->a */ 946 /* PS mode e->a */
897 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); 947 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
898} 948}
899 949
950static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)
951{
952 struct fb_info *info = hdmi->info;
953 struct sh_mobile_lcdc_chan *ch = info->par;
954 struct fb_var_screeninfo *new_var = &hdmi->var, *old_var = &ch->display_var;
955 struct fb_videomode mode1, mode2;
956
957 fb_var_to_videomode(&mode1, old_var);
958 fb_var_to_videomode(&mode2, new_var);
959
960 dev_dbg(info->dev, "Old %ux%u, new %ux%u\n",
961 mode1.xres, mode1.yres, mode2.xres, mode2.yres);
962
963 if (fb_mode_is_equal(&mode1, &mode2))
964 return false;
965
966 dev_dbg(info->dev, "Switching %u -> %u lines\n",
967 mode1.yres, mode2.yres);
968 *old_var = *new_var;
969
970 return true;
971}
972
973/**
974 * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
975 * @hdmi: driver context
976 * @pixclock: pixel clock period in picoseconds
977 * return: configured positive rate if successful
978 * 0 if couldn't set the rate, but managed to enable the clock
979 * negative error, if couldn't enable the clock
980 */
981static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long pixclock)
982{
983 long rate;
984 int ret;
985
986 rate = PICOS2KHZ(pixclock) * 1000;
987 rate = clk_round_rate(hdmi->hdmi_clk, rate);
988 if (rate > 0) {
989 ret = clk_set_rate(hdmi->hdmi_clk, rate);
990 if (ret < 0) {
991 dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", rate, ret);
992 rate = 0;
993 } else {
994 dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", rate);
995 }
996 } else {
997 rate = 0;
998 dev_warn(hdmi->dev, "Cannot get suitable rate: %ld\n", rate);
999 }
1000
1001 ret = clk_enable(hdmi->hdmi_clk);
1002 if (ret < 0) {
1003 dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
1004 return ret;
1005 }
1006
1007 return rate;
1008}
1009
900/* Hotplug interrupt occurred, read EDID */ 1010/* Hotplug interrupt occurred, read EDID */
901static void edid_work_fn(struct work_struct *work) 1011static void sh_hdmi_edid_work_fn(struct work_struct *work)
902{ 1012{
903 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); 1013 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
904 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 1014 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1015 struct sh_mobile_lcdc_chan *ch;
1016 int ret;
905 1017
906 pr_debug("%s(%p): begin, hotplug status %d\n", __func__, 1018 dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__,
907 pdata->lcd_dev, hdmi->hp_state); 1019 pdata->lcd_dev, hdmi->hp_state);
908 1020
909 if (!pdata->lcd_dev) 1021 if (!pdata->lcd_dev)
910 return; 1022 return;
911 1023
1024 mutex_lock(&hdmi->mutex);
1025
912 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { 1026 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
913 pm_runtime_get_sync(hdmi->dev);
914 /* A device has been plugged in */ 1027 /* A device has been plugged in */
915 sh_hdmi_read_edid(hdmi); 1028 pm_runtime_get_sync(hdmi->dev);
1029
1030 ret = sh_hdmi_read_edid(hdmi);
1031 if (ret < 0)
1032 goto out;
1033
1034 /* Reconfigure the clock */
1035 clk_disable(hdmi->hdmi_clk);
1036 ret = sh_hdmi_clk_configure(hdmi, hdmi->var.pixclock);
1037 if (ret < 0)
1038 goto out;
1039
916 msleep(10); 1040 msleep(10);
917 sh_hdmi_configure(hdmi); 1041 sh_hdmi_configure(hdmi);
918 /* Switched to another (d) power-save mode */ 1042 /* Switched to another (d) power-save mode */
919 msleep(10); 1043 msleep(10);
920 1044
921 if (!hdmi->info) 1045 if (!hdmi->info)
922 return; 1046 goto out;
1047
1048 ch = hdmi->info->par;
923 1049
924 acquire_console_sem(); 1050 acquire_console_sem();
925 1051
926 /* HDMI plug in */ 1052 /* HDMI plug in */
927 hdmi->info->var = hdmi->var; 1053 if (!sh_hdmi_must_reconfigure(hdmi) &&
928 if (hdmi->info->state != FBINFO_STATE_RUNNING) 1054 hdmi->info->state == FBINFO_STATE_RUNNING) {
1055 /*
1056 * First activation with the default monitor - just turn
1057 * on, if we run a resume here, the logo disappears
1058 */
1059 if (lock_fb_info(hdmi->info)) {
1060 sh_hdmi_display_on(hdmi, hdmi->info);
1061 unlock_fb_info(hdmi->info);
1062 }
1063 } else {
1064 /* New monitor or have to wake up */
929 fb_set_suspend(hdmi->info, 0); 1065 fb_set_suspend(hdmi->info, 0);
930 else 1066 }
931 hdmi_display_on(hdmi, hdmi->info);
932 1067
933 release_console_sem(); 1068 release_console_sem();
934 } else { 1069 } else {
1070 ret = 0;
935 if (!hdmi->info) 1071 if (!hdmi->info)
936 return; 1072 goto out;
937 1073
938 acquire_console_sem(); 1074 acquire_console_sem();
939 1075
@@ -942,15 +1078,67 @@ static void edid_work_fn(struct work_struct *work)
942 1078
943 release_console_sem(); 1079 release_console_sem();
944 pm_runtime_put(hdmi->dev); 1080 pm_runtime_put(hdmi->dev);
1081 fb_destroy_modedb(hdmi->monspec.modedb);
945 } 1082 }
946 1083
947 pr_debug("%s(%p): end\n", __func__, pdata->lcd_dev); 1084out:
1085 if (ret < 0)
1086 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
1087 mutex_unlock(&hdmi->mutex);
1088
1089 dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, pdata->lcd_dev);
1090}
1091
1092static int sh_hdmi_notify(struct notifier_block *nb,
1093 unsigned long action, void *data);
1094
1095static struct notifier_block sh_hdmi_notifier = {
1096 .notifier_call = sh_hdmi_notify,
1097};
1098
1099static int sh_hdmi_notify(struct notifier_block *nb,
1100 unsigned long action, void *data)
1101{
1102 struct fb_event *event = data;
1103 struct fb_info *info = event->info;
1104 struct sh_mobile_lcdc_chan *ch = info->par;
1105 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
1106 struct sh_hdmi *hdmi = board_cfg->board_data;
1107
1108 if (nb != &sh_hdmi_notifier || !hdmi || hdmi->info != info)
1109 return NOTIFY_DONE;
1110
1111 switch(action) {
1112 case FB_EVENT_FB_REGISTERED:
1113 /* Unneeded, activation taken care by sh_hdmi_display_on() */
1114 break;
1115 case FB_EVENT_FB_UNREGISTERED:
1116 /*
1117 * We are called from unregister_framebuffer() with the
1118 * info->lock held. This is bad for us, because we can race with
1119 * the scheduled work, which has to call fb_set_suspend(), which
1120 * takes info->lock internally, so, sh_hdmi_edid_work_fn()
1121 * cannot take and hold info->lock for the whole function
1122 * duration. Using an additional lock creates a classical AB-BA
1123 * lock up. Therefore, we have to release the info->lock
1124 * temporarily, synchronise with the work queue and re-acquire
1125 * the info->lock.
1126 */
1127 unlock_fb_info(hdmi->info);
1128 mutex_lock(&hdmi->mutex);
1129 hdmi->info = NULL;
1130 mutex_unlock(&hdmi->mutex);
1131 lock_fb_info(hdmi->info);
1132 return NOTIFY_OK;
1133 }
1134 return NOTIFY_DONE;
948} 1135}
949 1136
950static int __init sh_hdmi_probe(struct platform_device *pdev) 1137static int __init sh_hdmi_probe(struct platform_device *pdev)
951{ 1138{
952 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1139 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
953 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1140 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1141 struct sh_mobile_lcdc_board_cfg *board_cfg;
954 int irq = platform_get_irq(pdev, 0), ret; 1142 int irq = platform_get_irq(pdev, 0), ret;
955 struct sh_hdmi *hdmi; 1143 struct sh_hdmi *hdmi;
956 long rate; 1144 long rate;
@@ -964,10 +1152,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
964 return -ENOMEM; 1152 return -ENOMEM;
965 } 1153 }
966 1154
967 ret = snd_soc_register_codec(&pdev->dev, 1155 mutex_init(&hdmi->mutex);
968 &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
969 if (ret < 0)
970 goto esndreg;
971 1156
972 hdmi->dev = &pdev->dev; 1157 hdmi->dev = &pdev->dev;
973 1158
@@ -978,30 +1163,14 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
978 goto egetclk; 1163 goto egetclk;
979 } 1164 }
980 1165
981 rate = PICOS2KHZ(pdata->lcd_chan->lcd_cfg.pixclock) * 1000; 1166 /* Some arbitrary relaxed pixclock just to get things started */
982 1167 rate = sh_hdmi_clk_configure(hdmi, 37037);
983 rate = clk_round_rate(hdmi->hdmi_clk, rate);
984 if (rate < 0) { 1168 if (rate < 0) {
985 ret = rate; 1169 ret = rate;
986 dev_err(&pdev->dev, "Cannot get suitable rate: %ld\n", rate);
987 goto erate; 1170 goto erate;
988 } 1171 }
989 1172
990 ret = clk_set_rate(hdmi->hdmi_clk, rate); 1173 dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
991 if (ret < 0) {
992 dev_err(&pdev->dev, "Cannot set rate %ld: %d\n", rate, ret);
993 goto erate;
994 }
995
996 pr_debug("HDMI set frequency %lu\n", rate);
997
998 ret = clk_enable(hdmi->hdmi_clk);
999 if (ret < 0) {
1000 dev_err(&pdev->dev, "Cannot enable clock: %d\n", ret);
1001 goto eclkenable;
1002 }
1003
1004 dev_info(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
1005 1174
1006 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { 1175 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
1007 dev_err(&pdev->dev, "HDMI register region already claimed\n"); 1176 dev_err(&pdev->dev, "HDMI register region already claimed\n");
@@ -1018,18 +1187,18 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1018 1187
1019 platform_set_drvdata(pdev, hdmi); 1188 platform_set_drvdata(pdev, hdmi);
1020 1189
1021#if 1
1022 /* Product and revision IDs are 0 in sh-mobile version */ 1190 /* Product and revision IDs are 0 in sh-mobile version */
1023 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", 1191 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
1024 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); 1192 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
1025#endif
1026 1193
1027 /* Set up LCDC callbacks */ 1194 /* Set up LCDC callbacks */
1028 pdata->lcd_chan->board_cfg.board_data = hdmi; 1195 board_cfg = &pdata->lcd_chan->board_cfg;
1029 pdata->lcd_chan->board_cfg.display_on = hdmi_display_on; 1196 board_cfg->owner = THIS_MODULE;
1030 pdata->lcd_chan->board_cfg.display_off = hdmi_display_off; 1197 board_cfg->board_data = hdmi;
1198 board_cfg->display_on = sh_hdmi_display_on;
1199 board_cfg->display_off = sh_hdmi_display_off;
1031 1200
1032 INIT_DELAYED_WORK(&hdmi->edid_work, edid_work_fn); 1201 INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn);
1033 1202
1034 pm_runtime_enable(&pdev->dev); 1203 pm_runtime_enable(&pdev->dev);
1035 pm_runtime_resume(&pdev->dev); 1204 pm_runtime_resume(&pdev->dev);
@@ -1041,8 +1210,17 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1041 goto ereqirq; 1210 goto ereqirq;
1042 } 1211 }
1043 1212
1213 ret = snd_soc_register_codec(&pdev->dev,
1214 &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
1215 if (ret < 0) {
1216 dev_err(&pdev->dev, "codec registration failed\n");
1217 goto ecodec;
1218 }
1219
1044 return 0; 1220 return 0;
1045 1221
1222ecodec:
1223 free_irq(irq, hdmi);
1046ereqirq: 1224ereqirq:
1047 pm_runtime_disable(&pdev->dev); 1225 pm_runtime_disable(&pdev->dev);
1048 iounmap(hdmi->base); 1226 iounmap(hdmi->base);
@@ -1050,12 +1228,10 @@ emap:
1050 release_mem_region(res->start, resource_size(res)); 1228 release_mem_region(res->start, resource_size(res));
1051ereqreg: 1229ereqreg:
1052 clk_disable(hdmi->hdmi_clk); 1230 clk_disable(hdmi->hdmi_clk);
1053eclkenable:
1054erate: 1231erate:
1055 clk_put(hdmi->hdmi_clk); 1232 clk_put(hdmi->hdmi_clk);
1056egetclk: 1233egetclk:
1057 snd_soc_unregister_codec(&pdev->dev); 1234 mutex_destroy(&hdmi->mutex);
1058esndreg:
1059 kfree(hdmi); 1235 kfree(hdmi);
1060 1236
1061 return ret; 1237 return ret;
@@ -1066,21 +1242,26 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
1066 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1242 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
1067 struct sh_hdmi *hdmi = platform_get_drvdata(pdev); 1243 struct sh_hdmi *hdmi = platform_get_drvdata(pdev);
1068 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1244 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1245 struct sh_mobile_lcdc_board_cfg *board_cfg = &pdata->lcd_chan->board_cfg;
1069 int irq = platform_get_irq(pdev, 0); 1246 int irq = platform_get_irq(pdev, 0);
1070 1247
1071 snd_soc_unregister_codec(&pdev->dev); 1248 snd_soc_unregister_codec(&pdev->dev);
1072 1249
1073 pdata->lcd_chan->board_cfg.display_on = NULL; 1250 board_cfg->display_on = NULL;
1074 pdata->lcd_chan->board_cfg.display_off = NULL; 1251 board_cfg->display_off = NULL;
1075 pdata->lcd_chan->board_cfg.board_data = NULL; 1252 board_cfg->board_data = NULL;
1253 board_cfg->owner = NULL;
1076 1254
1255 /* No new work will be scheduled, wait for running ISR */
1077 free_irq(irq, hdmi); 1256 free_irq(irq, hdmi);
1078 pm_runtime_disable(&pdev->dev); 1257 /* Wait for already scheduled work */
1079 cancel_delayed_work_sync(&hdmi->edid_work); 1258 cancel_delayed_work_sync(&hdmi->edid_work);
1259 pm_runtime_disable(&pdev->dev);
1080 clk_disable(hdmi->hdmi_clk); 1260 clk_disable(hdmi->hdmi_clk);
1081 clk_put(hdmi->hdmi_clk); 1261 clk_put(hdmi->hdmi_clk);
1082 iounmap(hdmi->base); 1262 iounmap(hdmi->base);
1083 release_mem_region(res->start, resource_size(res)); 1263 release_mem_region(res->start, resource_size(res));
1264 mutex_destroy(&hdmi->mutex);
1084 kfree(hdmi); 1265 kfree(hdmi);
1085 1266
1086 return 0; 1267 return 0;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 7a1419279c8f..50963739a409 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -12,7 +12,6 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/mm.h> 14#include <linux/mm.h>
15#include <linux/fb.h>
16#include <linux/clk.h> 15#include <linux/clk.h>
17#include <linux/pm_runtime.h> 16#include <linux/pm_runtime.h>
18#include <linux/platform_device.h> 17#include <linux/platform_device.h>
@@ -21,10 +20,12 @@
21#include <linux/vmalloc.h> 20#include <linux/vmalloc.h>
22#include <linux/ioctl.h> 21#include <linux/ioctl.h>
23#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/console.h>
24#include <video/sh_mobile_lcdc.h> 24#include <video/sh_mobile_lcdc.h>
25#include <asm/atomic.h> 25#include <asm/atomic.h>
26 26
27#define PALETTE_NR 16 27#include "sh_mobile_lcdcfb.h"
28
28#define SIDE_B_OFFSET 0x1000 29#define SIDE_B_OFFSET 0x1000
29#define MIRROR_OFFSET 0x2000 30#define MIRROR_OFFSET 0x2000
30 31
@@ -53,11 +54,8 @@ static int lcdc_shared_regs[] = {
53}; 54};
54#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) 55#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
55 56
56/* per-channel registers */ 57#define DEFAULT_XRES 1280
57enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, 58#define DEFAULT_YRES 1024
58 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
59 LDHAJR,
60 NR_CH_REGS };
61 59
62static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 60static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
63 [LDDCKPAT1R] = 0x400, 61 [LDDCKPAT1R] = 0x400,
@@ -112,23 +110,21 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
112#define LDRCNTR_MRC 0x00000001 110#define LDRCNTR_MRC 0x00000001
113#define LDSR_MRS 0x00000100 111#define LDSR_MRS 0x00000100
114 112
115struct sh_mobile_lcdc_priv; 113static const struct fb_videomode default_720p = {
116struct sh_mobile_lcdc_chan { 114 .name = "HDMI 720p",
117 struct sh_mobile_lcdc_priv *lcdc; 115 .xres = 1280,
118 unsigned long *reg_offs; 116 .yres = 720,
119 unsigned long ldmt1r_value; 117
120 unsigned long enabled; /* ME and SE in LDCNT2R */ 118 .left_margin = 200,
121 struct sh_mobile_lcdc_chan_cfg cfg; 119 .right_margin = 88,
122 u32 pseudo_palette[PALETTE_NR]; 120 .hsync_len = 48,
123 unsigned long saved_ch_regs[NR_CH_REGS]; 121
124 struct fb_info *info; 122 .upper_margin = 20,
125 dma_addr_t dma_handle; 123 .lower_margin = 5,
126 struct fb_deferred_io defio; 124 .vsync_len = 5,
127 struct scatterlist *sglist; 125
128 unsigned long frame_end; 126 .pixclock = 13468,
129 unsigned long pan_offset; 127 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
130 wait_queue_head_t frame_end_wait;
131 struct completion vsync_completion;
132}; 128};
133 129
134struct sh_mobile_lcdc_priv { 130struct sh_mobile_lcdc_priv {
@@ -409,8 +405,8 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
409 405
410static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) 406static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
411{ 407{
412 struct fb_var_screeninfo *var = &ch->info->var; 408 struct fb_var_screeninfo *var = &ch->info->var, *display_var = &ch->display_var;
413 unsigned long h_total, hsync_pos; 409 unsigned long h_total, hsync_pos, display_h_total;
414 u32 tmp; 410 u32 tmp;
415 411
416 tmp = ch->ldmt1r_value; 412 tmp = ch->ldmt1r_value;
@@ -428,31 +424,33 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
428 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r); 424 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
429 425
430 /* horizontal configuration */ 426 /* horizontal configuration */
431 h_total = var->xres + var->hsync_len + 427 h_total = display_var->xres + display_var->hsync_len +
432 var->left_margin + var->right_margin; 428 display_var->left_margin + display_var->right_margin;
433 tmp = h_total / 8; /* HTCN */ 429 tmp = h_total / 8; /* HTCN */
434 tmp |= (var->xres / 8) << 16; /* HDCN */ 430 tmp |= (min(display_var->xres, var->xres) / 8) << 16; /* HDCN */
435 lcdc_write_chan(ch, LDHCNR, tmp); 431 lcdc_write_chan(ch, LDHCNR, tmp);
436 432
437 hsync_pos = var->xres + var->right_margin; 433 hsync_pos = display_var->xres + display_var->right_margin;
438 tmp = hsync_pos / 8; /* HSYNP */ 434 tmp = hsync_pos / 8; /* HSYNP */
439 tmp |= (var->hsync_len / 8) << 16; /* HSYNW */ 435 tmp |= (display_var->hsync_len / 8) << 16; /* HSYNW */
440 lcdc_write_chan(ch, LDHSYNR, tmp); 436 lcdc_write_chan(ch, LDHSYNR, tmp);
441 437
442 /* vertical configuration */ 438 /* vertical configuration */
443 tmp = var->yres + var->vsync_len + 439 tmp = display_var->yres + display_var->vsync_len +
444 var->upper_margin + var->lower_margin; /* VTLN */ 440 display_var->upper_margin + display_var->lower_margin; /* VTLN */
445 tmp |= var->yres << 16; /* VDLN */ 441 tmp |= min(display_var->yres, var->yres) << 16; /* VDLN */
446 lcdc_write_chan(ch, LDVLNR, tmp); 442 lcdc_write_chan(ch, LDVLNR, tmp);
447 443
448 tmp = var->yres + var->lower_margin; /* VSYNP */ 444 tmp = display_var->yres + display_var->lower_margin; /* VSYNP */
449 tmp |= var->vsync_len << 16; /* VSYNW */ 445 tmp |= display_var->vsync_len << 16; /* VSYNW */
450 lcdc_write_chan(ch, LDVSYNR, tmp); 446 lcdc_write_chan(ch, LDVSYNR, tmp);
451 447
452 /* Adjust horizontal synchronisation for HDMI */ 448 /* Adjust horizontal synchronisation for HDMI */
453 tmp = ((var->xres & 7) << 24) | 449 display_h_total = display_var->xres + display_var->hsync_len +
454 ((h_total & 7) << 16) | 450 display_var->left_margin + display_var->right_margin;
455 ((var->hsync_len & 7) << 8) | 451 tmp = ((display_var->xres & 7) << 24) |
452 ((display_h_total & 7) << 16) |
453 ((display_var->hsync_len & 7) << 8) |
456 hsync_pos; 454 hsync_pos;
457 lcdc_write_chan(ch, LDHAJR, tmp); 455 lcdc_write_chan(ch, LDHAJR, tmp);
458} 456}
@@ -460,7 +458,6 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
460static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 458static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
461{ 459{
462 struct sh_mobile_lcdc_chan *ch; 460 struct sh_mobile_lcdc_chan *ch;
463 struct fb_videomode *lcd_cfg;
464 struct sh_mobile_lcdc_board_cfg *board_cfg; 461 struct sh_mobile_lcdc_board_cfg *board_cfg;
465 unsigned long tmp; 462 unsigned long tmp;
466 int k, m; 463 int k, m;
@@ -503,7 +500,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
503 m = 1 << 6; 500 m = 1 << 6;
504 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); 501 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
505 502
506 lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000); 503 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */
504 lcdc_write_chan(ch, LDDCKPAT1R, 0);
507 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); 505 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
508 } 506 }
509 507
@@ -518,7 +516,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
518 516
519 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 517 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
520 ch = &priv->ch[k]; 518 ch = &priv->ch[k];
521 lcd_cfg = &ch->cfg.lcd_cfg;
522 519
523 if (!ch->enabled) 520 if (!ch->enabled)
524 continue; 521 continue;
@@ -547,7 +544,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
547 544
548 /* set bpp format in PKF[4:0] */ 545 /* set bpp format in PKF[4:0] */
549 tmp = lcdc_read_chan(ch, LDDFR); 546 tmp = lcdc_read_chan(ch, LDDFR);
550 tmp &= ~(0x0001001f); 547 tmp &= ~0x0001001f;
551 tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0; 548 tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0;
552 lcdc_write_chan(ch, LDDFR, tmp); 549 lcdc_write_chan(ch, LDDFR, tmp);
553 550
@@ -591,8 +588,10 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
591 continue; 588 continue;
592 589
593 board_cfg = &ch->cfg.board_cfg; 590 board_cfg = &ch->cfg.board_cfg;
594 if (board_cfg->display_on) 591 if (try_module_get(board_cfg->owner) && board_cfg->display_on) {
595 board_cfg->display_on(board_cfg->board_data, ch->info); 592 board_cfg->display_on(board_cfg->board_data, ch->info);
593 module_put(board_cfg->owner);
594 }
596 } 595 }
597 596
598 return 0; 597 return 0;
@@ -614,7 +613,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
614 * flush frame, and wait for frame end interrupt 613 * flush frame, and wait for frame end interrupt
615 * clean up deferred io and enable clock 614 * clean up deferred io and enable clock
616 */ 615 */
617 if (ch->info->fbdefio) { 616 if (ch->info && ch->info->fbdefio) {
618 ch->frame_end = 0; 617 ch->frame_end = 0;
619 schedule_delayed_work(&ch->info->deferred_work, 0); 618 schedule_delayed_work(&ch->info->deferred_work, 0);
620 wait_event(ch->frame_end_wait, ch->frame_end); 619 wait_event(ch->frame_end_wait, ch->frame_end);
@@ -624,8 +623,10 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
624 } 623 }
625 624
626 board_cfg = &ch->cfg.board_cfg; 625 board_cfg = &ch->cfg.board_cfg;
627 if (board_cfg->display_off) 626 if (try_module_get(board_cfg->owner) && board_cfg->display_off) {
628 board_cfg->display_off(board_cfg->board_data); 627 board_cfg->display_off(board_cfg->board_data);
628 module_put(board_cfg->owner);
629 }
629 } 630 }
630 631
631 /* stop the lcdc */ 632 /* stop the lcdc */
@@ -704,7 +705,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
704 return PTR_ERR(priv->dot_clk); 705 return PTR_ERR(priv->dot_clk);
705 } 706 }
706 } 707 }
707 atomic_set(&priv->hw_usecnt, -1);
708 708
709 /* Runtime PM support involves two step for this driver: 709 /* Runtime PM support involves two step for this driver:
710 * 1) Enable Runtime PM 710 * 1) Enable Runtime PM
@@ -837,6 +837,102 @@ static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
837 return retval; 837 return retval;
838} 838}
839 839
840static void sh_mobile_fb_reconfig(struct fb_info *info)
841{
842 struct sh_mobile_lcdc_chan *ch = info->par;
843 struct fb_videomode mode1, mode2;
844 struct fb_event event;
845 int evnt = FB_EVENT_MODE_CHANGE_ALL;
846
847 if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par))
848 /* More framebuffer users are active */
849 return;
850
851 fb_var_to_videomode(&mode1, &ch->display_var);
852 fb_var_to_videomode(&mode2, &info->var);
853
854 if (fb_mode_is_equal(&mode1, &mode2))
855 return;
856
857 /* Display has been re-plugged, framebuffer is free now, reconfigure */
858 if (fb_set_var(info, &ch->display_var) < 0)
859 /* Couldn't reconfigure, hopefully, can continue as before */
860 return;
861
862 info->fix.line_length = mode2.xres * (ch->cfg.bpp / 8);
863
864 /*
865 * fb_set_var() calls the notifier change internally, only if
866 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
867 * user event, we have to call the chain ourselves.
868 */
869 event.info = info;
870 event.data = &mode2;
871 fb_notifier_call_chain(evnt, &event);
872}
873
874/*
875 * Locking: both .fb_release() and .fb_open() are called with info->lock held if
876 * user == 1, or with console sem held, if user == 0.
877 */
878static int sh_mobile_release(struct fb_info *info, int user)
879{
880 struct sh_mobile_lcdc_chan *ch = info->par;
881
882 mutex_lock(&ch->open_lock);
883 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
884
885 ch->use_count--;
886
887 /* Nothing to reconfigure, when called from fbcon */
888 if (user) {
889 acquire_console_sem();
890 sh_mobile_fb_reconfig(info);
891 release_console_sem();
892 }
893
894 mutex_unlock(&ch->open_lock);
895
896 return 0;
897}
898
899static int sh_mobile_open(struct fb_info *info, int user)
900{
901 struct sh_mobile_lcdc_chan *ch = info->par;
902
903 mutex_lock(&ch->open_lock);
904 ch->use_count++;
905
906 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
907 mutex_unlock(&ch->open_lock);
908
909 return 0;
910}
911
912static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
913{
914 struct sh_mobile_lcdc_chan *ch = info->par;
915
916 if (var->xres < 160 || var->xres > 1920 ||
917 var->yres < 120 || var->yres > 1080 ||
918 var->left_margin < 32 || var->left_margin > 320 ||
919 var->right_margin < 12 || var->right_margin > 240 ||
920 var->upper_margin < 12 || var->upper_margin > 120 ||
921 var->lower_margin < 1 || var->lower_margin > 64 ||
922 var->hsync_len < 32 || var->hsync_len > 240 ||
923 var->vsync_len < 2 || var->vsync_len > 64 ||
924 var->pixclock < 6000 || var->pixclock > 40000 ||
925 var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) {
926 dev_warn(info->dev, "Invalid info: %u %u %u %u %u %u %u %u %u!\n",
927 var->xres, var->yres,
928 var->left_margin, var->right_margin,
929 var->upper_margin, var->lower_margin,
930 var->hsync_len, var->vsync_len,
931 var->pixclock);
932 return -EINVAL;
933 }
934 return 0;
935}
840 936
841static struct fb_ops sh_mobile_lcdc_ops = { 937static struct fb_ops sh_mobile_lcdc_ops = {
842 .owner = THIS_MODULE, 938 .owner = THIS_MODULE,
@@ -848,6 +944,9 @@ static struct fb_ops sh_mobile_lcdc_ops = {
848 .fb_imageblit = sh_mobile_lcdc_imageblit, 944 .fb_imageblit = sh_mobile_lcdc_imageblit,
849 .fb_pan_display = sh_mobile_fb_pan_display, 945 .fb_pan_display = sh_mobile_fb_pan_display,
850 .fb_ioctl = sh_mobile_ioctl, 946 .fb_ioctl = sh_mobile_ioctl,
947 .fb_open = sh_mobile_open,
948 .fb_release = sh_mobile_release,
949 .fb_check_var = sh_mobile_check_var,
851}; 950};
852 951
853static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) 952static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
@@ -958,6 +1057,7 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
958 .runtime_resume = sh_mobile_lcdc_runtime_resume, 1057 .runtime_resume = sh_mobile_lcdc_runtime_resume,
959}; 1058};
960 1059
1060/* locking: called with info->lock held */
961static int sh_mobile_lcdc_notify(struct notifier_block *nb, 1061static int sh_mobile_lcdc_notify(struct notifier_block *nb,
962 unsigned long action, void *data) 1062 unsigned long action, void *data)
963{ 1063{
@@ -965,53 +1065,40 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
965 struct fb_info *info = event->info; 1065 struct fb_info *info = event->info;
966 struct sh_mobile_lcdc_chan *ch = info->par; 1066 struct sh_mobile_lcdc_chan *ch = info->par;
967 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; 1067 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
968 struct fb_var_screeninfo *var; 1068 int ret;
969 1069
970 if (&ch->lcdc->notifier != nb) 1070 if (&ch->lcdc->notifier != nb)
971 return 0; 1071 return NOTIFY_DONE;
972 1072
973 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", 1073 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
974 __func__, action, event->data); 1074 __func__, action, event->data);
975 1075
976 switch(action) { 1076 switch(action) {
977 case FB_EVENT_SUSPEND: 1077 case FB_EVENT_SUSPEND:
978 if (board_cfg->display_off) 1078 if (try_module_get(board_cfg->owner) && board_cfg->display_off) {
979 board_cfg->display_off(board_cfg->board_data); 1079 board_cfg->display_off(board_cfg->board_data);
1080 module_put(board_cfg->owner);
1081 }
980 pm_runtime_put(info->device); 1082 pm_runtime_put(info->device);
1083 sh_mobile_lcdc_stop(ch->lcdc);
981 break; 1084 break;
982 case FB_EVENT_RESUME: 1085 case FB_EVENT_RESUME:
983 var = &info->var; 1086 mutex_lock(&ch->open_lock);
1087 sh_mobile_fb_reconfig(info);
1088 mutex_unlock(&ch->open_lock);
984 1089
985 /* HDMI must be enabled before LCDC configuration */ 1090 /* HDMI must be enabled before LCDC configuration */
986 if (board_cfg->display_on) 1091 if (try_module_get(board_cfg->owner) && board_cfg->display_on) {
987 board_cfg->display_on(board_cfg->board_data, ch->info); 1092 board_cfg->display_on(board_cfg->board_data, info);
988 1093 module_put(board_cfg->owner);
989 /* Check if the new display is not in our modelist */
990 if (ch->info->modelist.next &&
991 !fb_match_mode(var, &ch->info->modelist)) {
992 struct fb_videomode mode;
993 int ret;
994
995 /* Can we handle this display? */
996 if (var->xres > ch->cfg.lcd_cfg.xres ||
997 var->yres > ch->cfg.lcd_cfg.yres)
998 return -ENOMEM;
999
1000 /* Add to the modelist */
1001 fb_var_to_videomode(&mode, var);
1002 ret = fb_add_videomode(&mode, &ch->info->modelist);
1003 if (ret < 0)
1004 return ret;
1005 } 1094 }
1006 1095
1007 pm_runtime_get_sync(info->device); 1096 ret = sh_mobile_lcdc_start(ch->lcdc);
1008 1097 if (!ret)
1009 sh_mobile_lcdc_geometry(ch); 1098 pm_runtime_get_sync(info->device);
1010
1011 break;
1012 } 1099 }
1013 1100
1014 return 0; 1101 return NOTIFY_OK;
1015} 1102}
1016 1103
1017static int sh_mobile_lcdc_remove(struct platform_device *pdev); 1104static int sh_mobile_lcdc_remove(struct platform_device *pdev);
@@ -1020,14 +1107,13 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1020{ 1107{
1021 struct fb_info *info; 1108 struct fb_info *info;
1022 struct sh_mobile_lcdc_priv *priv; 1109 struct sh_mobile_lcdc_priv *priv;
1023 struct sh_mobile_lcdc_info *pdata; 1110 struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
1024 struct sh_mobile_lcdc_chan_cfg *cfg;
1025 struct resource *res; 1111 struct resource *res;
1026 int error; 1112 int error;
1027 void *buf; 1113 void *buf;
1028 int i, j; 1114 int i, j;
1029 1115
1030 if (!pdev->dev.platform_data) { 1116 if (!pdata) {
1031 dev_err(&pdev->dev, "no platform data defined\n"); 1117 dev_err(&pdev->dev, "no platform data defined\n");
1032 return -EINVAL; 1118 return -EINVAL;
1033 } 1119 }
@@ -1055,31 +1141,33 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1055 } 1141 }
1056 1142
1057 priv->irq = i; 1143 priv->irq = i;
1058 pdata = pdev->dev.platform_data; 1144 atomic_set(&priv->hw_usecnt, -1);
1059 1145
1060 j = 0; 1146 j = 0;
1061 for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) { 1147 for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
1062 priv->ch[j].lcdc = priv; 1148 struct sh_mobile_lcdc_chan *ch = priv->ch + j;
1063 memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i])); 1149
1150 ch->lcdc = priv;
1151 memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
1064 1152
1065 error = sh_mobile_lcdc_check_interface(&priv->ch[j]); 1153 error = sh_mobile_lcdc_check_interface(ch);
1066 if (error) { 1154 if (error) {
1067 dev_err(&pdev->dev, "unsupported interface type\n"); 1155 dev_err(&pdev->dev, "unsupported interface type\n");
1068 goto err1; 1156 goto err1;
1069 } 1157 }
1070 init_waitqueue_head(&priv->ch[j].frame_end_wait); 1158 init_waitqueue_head(&ch->frame_end_wait);
1071 init_completion(&priv->ch[j].vsync_completion); 1159 init_completion(&ch->vsync_completion);
1072 priv->ch[j].pan_offset = 0; 1160 ch->pan_offset = 0;
1073 1161
1074 switch (pdata->ch[i].chan) { 1162 switch (pdata->ch[i].chan) {
1075 case LCDC_CHAN_MAINLCD: 1163 case LCDC_CHAN_MAINLCD:
1076 priv->ch[j].enabled = 1 << 1; 1164 ch->enabled = 1 << 1;
1077 priv->ch[j].reg_offs = lcdc_offs_mainlcd; 1165 ch->reg_offs = lcdc_offs_mainlcd;
1078 j++; 1166 j++;
1079 break; 1167 break;
1080 case LCDC_CHAN_SUBLCD: 1168 case LCDC_CHAN_SUBLCD:
1081 priv->ch[j].enabled = 1 << 2; 1169 ch->enabled = 1 << 2;
1082 priv->ch[j].reg_offs = lcdc_offs_sublcd; 1170 ch->reg_offs = lcdc_offs_sublcd;
1083 j++; 1171 j++;
1084 break; 1172 break;
1085 } 1173 }
@@ -1103,69 +1191,83 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1103 1191
1104 for (i = 0; i < j; i++) { 1192 for (i = 0; i < j; i++) {
1105 struct fb_var_screeninfo *var; 1193 struct fb_var_screeninfo *var;
1106 struct fb_videomode *lcd_cfg; 1194 const struct fb_videomode *lcd_cfg, *max_cfg = NULL;
1107 cfg = &priv->ch[i].cfg; 1195 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1196 struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg;
1197 const struct fb_videomode *mode = cfg->lcd_cfg;
1198 unsigned long max_size = 0;
1199 int k;
1108 1200
1109 priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); 1201 ch->info = framebuffer_alloc(0, &pdev->dev);
1110 if (!priv->ch[i].info) { 1202 if (!ch->info) {
1111 dev_err(&pdev->dev, "unable to allocate fb_info\n"); 1203 dev_err(&pdev->dev, "unable to allocate fb_info\n");
1112 error = -ENOMEM; 1204 error = -ENOMEM;
1113 break; 1205 break;
1114 } 1206 }
1115 1207
1116 info = priv->ch[i].info; 1208 info = ch->info;
1117 var = &info->var; 1209 var = &info->var;
1118 lcd_cfg = &cfg->lcd_cfg;
1119 info->fbops = &sh_mobile_lcdc_ops; 1210 info->fbops = &sh_mobile_lcdc_ops;
1120 var->xres = var->xres_virtual = lcd_cfg->xres; 1211 info->par = ch;
1121 var->yres = lcd_cfg->yres; 1212
1213 mutex_init(&ch->open_lock);
1214
1215 for (k = 0, lcd_cfg = mode;
1216 k < cfg->num_cfg && lcd_cfg;
1217 k++, lcd_cfg++) {
1218 unsigned long size = lcd_cfg->yres * lcd_cfg->xres;
1219
1220 if (size > max_size) {
1221 max_cfg = lcd_cfg;
1222 max_size = size;
1223 }
1224 }
1225
1226 if (!mode)
1227 max_size = DEFAULT_XRES * DEFAULT_YRES;
1228 else if (max_cfg)
1229 dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
1230 max_cfg->xres, max_cfg->yres);
1231
1232 info->fix = sh_mobile_lcdc_fix;
1233 info->fix.smem_len = max_size * (cfg->bpp / 8) * 2;
1234
1235 if (!mode)
1236 mode = &default_720p;
1237
1238 fb_videomode_to_var(var, mode);
1122 /* Default Y virtual resolution is 2x panel size */ 1239 /* Default Y virtual resolution is 2x panel size */
1123 var->yres_virtual = var->yres * 2; 1240 var->yres_virtual = var->yres * 2;
1124 var->width = cfg->lcd_size_cfg.width;
1125 var->height = cfg->lcd_size_cfg.height;
1126 var->activate = FB_ACTIVATE_NOW; 1241 var->activate = FB_ACTIVATE_NOW;
1127 var->left_margin = lcd_cfg->left_margin;
1128 var->right_margin = lcd_cfg->right_margin;
1129 var->upper_margin = lcd_cfg->upper_margin;
1130 var->lower_margin = lcd_cfg->lower_margin;
1131 var->hsync_len = lcd_cfg->hsync_len;
1132 var->vsync_len = lcd_cfg->vsync_len;
1133 var->sync = lcd_cfg->sync;
1134 var->pixclock = lcd_cfg->pixclock;
1135 1242
1136 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp); 1243 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp);
1137 if (error) 1244 if (error)
1138 break; 1245 break;
1139 1246
1140 info->fix = sh_mobile_lcdc_fix;
1141 info->fix.line_length = lcd_cfg->xres * (cfg->bpp / 8);
1142 info->fix.smem_len = info->fix.line_length *
1143 var->yres_virtual;
1144
1145 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, 1247 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
1146 &priv->ch[i].dma_handle, GFP_KERNEL); 1248 &ch->dma_handle, GFP_KERNEL);
1147 if (!buf) { 1249 if (!buf) {
1148 dev_err(&pdev->dev, "unable to allocate buffer\n"); 1250 dev_err(&pdev->dev, "unable to allocate buffer\n");
1149 error = -ENOMEM; 1251 error = -ENOMEM;
1150 break; 1252 break;
1151 } 1253 }
1152 1254
1153 info->pseudo_palette = &priv->ch[i].pseudo_palette; 1255 info->pseudo_palette = &ch->pseudo_palette;
1154 info->flags = FBINFO_FLAG_DEFAULT; 1256 info->flags = FBINFO_FLAG_DEFAULT;
1155 1257
1156 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); 1258 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1157 if (error < 0) { 1259 if (error < 0) {
1158 dev_err(&pdev->dev, "unable to allocate cmap\n"); 1260 dev_err(&pdev->dev, "unable to allocate cmap\n");
1159 dma_free_coherent(&pdev->dev, info->fix.smem_len, 1261 dma_free_coherent(&pdev->dev, info->fix.smem_len,
1160 buf, priv->ch[i].dma_handle); 1262 buf, ch->dma_handle);
1161 break; 1263 break;
1162 } 1264 }
1163 1265
1164 memset(buf, 0, info->fix.smem_len); 1266 info->fix.smem_start = ch->dma_handle;
1165 info->fix.smem_start = priv->ch[i].dma_handle; 1267 info->fix.line_length = var->xres * (cfg->bpp / 8);
1166 info->screen_base = buf; 1268 info->screen_base = buf;
1167 info->device = &pdev->dev; 1269 info->device = &pdev->dev;
1168 info->par = &priv->ch[i]; 1270 ch->display_var = *var;
1169 } 1271 }
1170 1272
1171 if (error) 1273 if (error)
@@ -1179,6 +1281,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1179 1281
1180 for (i = 0; i < j; i++) { 1282 for (i = 0; i < j; i++) {
1181 struct sh_mobile_lcdc_chan *ch = priv->ch + i; 1283 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1284 const struct fb_videomode *mode = ch->cfg.lcd_cfg;
1285
1286 if (!mode)
1287 mode = &default_720p;
1182 1288
1183 info = ch->info; 1289 info = ch->info;
1184 1290
@@ -1191,6 +1297,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1191 } 1297 }
1192 } 1298 }
1193 1299
1300 fb_videomode_to_modelist(mode, ch->cfg.num_cfg, &info->modelist);
1194 error = register_framebuffer(info); 1301 error = register_framebuffer(info);
1195 if (error < 0) 1302 if (error < 0)
1196 goto err1; 1303 goto err1;
@@ -1200,8 +1307,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1200 pdev->name, 1307 pdev->name,
1201 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? 1308 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
1202 "mainlcd" : "sublcd", 1309 "mainlcd" : "sublcd",
1203 (int) ch->cfg.lcd_cfg.xres, 1310 info->var.xres, info->var.yres,
1204 (int) ch->cfg.lcd_cfg.yres,
1205 ch->cfg.bpp); 1311 ch->cfg.bpp);
1206 1312
1207 /* deferred io mode: disable clock to save power */ 1313 /* deferred io mode: disable clock to save power */
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
new file mode 100644
index 000000000000..9ecee2fba1d7
--- /dev/null
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -0,0 +1,41 @@
1#ifndef SH_MOBILE_LCDCFB_H
2#define SH_MOBILE_LCDCFB_H
3
4#include <linux/completion.h>
5#include <linux/fb.h>
6#include <linux/mutex.h>
7#include <linux/wait.h>
8
9/* per-channel registers */
10enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
11 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
12 LDHAJR,
13 NR_CH_REGS };
14
15#define PALETTE_NR 16
16
17struct sh_mobile_lcdc_priv;
18struct fb_info;
19
20struct sh_mobile_lcdc_chan {
21 struct sh_mobile_lcdc_priv *lcdc;
22 unsigned long *reg_offs;
23 unsigned long ldmt1r_value;
24 unsigned long enabled; /* ME and SE in LDCNT2R */
25 struct sh_mobile_lcdc_chan_cfg cfg;
26 u32 pseudo_palette[PALETTE_NR];
27 unsigned long saved_ch_regs[NR_CH_REGS];
28 struct fb_info *info;
29 dma_addr_t dma_handle;
30 struct fb_deferred_io defio;
31 struct scatterlist *sglist;
32 unsigned long frame_end;
33 unsigned long pan_offset;
34 wait_queue_head_t frame_end_wait;
35 struct completion vsync_completion;
36 struct fb_var_screeninfo display_var;
37 int use_count;
38 struct mutex open_lock; /* protects the use counter */
39};
40
41#endif