diff options
94 files changed, 5467 insertions, 2155 deletions
diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS index 888ae7b83ae4..a564ceea9e98 100644 --- a/Documentation/arm/OMAP/DSS +++ b/Documentation/arm/OMAP/DSS | |||
| @@ -47,6 +47,51 @@ flexible way to enable non-common multi-display configuration. In addition to | |||
| 47 | modelling the hardware overlays, omapdss supports virtual overlays and overlay | 47 | modelling the hardware overlays, omapdss supports virtual overlays and overlay |
| 48 | managers. These can be used when updating a display with CPU or system DMA. | 48 | managers. These can be used when updating a display with CPU or system DMA. |
| 49 | 49 | ||
| 50 | omapdss driver support for audio | ||
| 51 | -------------------------------- | ||
| 52 | There exist several display technologies and standards that support audio as | ||
| 53 | well. Hence, it is relevant to update the DSS device driver to provide an audio | ||
| 54 | interface that may be used by an audio driver or any other driver interested in | ||
| 55 | the functionality. | ||
| 56 | |||
| 57 | The audio_enable function is intended to prepare the relevant | ||
| 58 | IP for playback (e.g., enabling an audio FIFO, taking in/out of reset | ||
| 59 | some IP, enabling companion chips, etc). It is intended to be called before | ||
| 60 | audio_start. The audio_disable function performs the reverse operation and is | ||
| 61 | intended to be called after audio_stop. | ||
| 62 | |||
| 63 | While a given DSS device driver may support audio, it is possible that for | ||
| 64 | certain configurations audio is not supported (e.g., an HDMI display using a | ||
| 65 | VESA video timing). The audio_supported function is intended to query whether | ||
| 66 | the current configuration of the display supports audio. | ||
| 67 | |||
| 68 | The audio_config function is intended to configure all the relevant audio | ||
| 69 | parameters of the display. In order to make the function independent of any | ||
| 70 | specific DSS device driver, a struct omap_dss_audio is defined. Its purpose | ||
| 71 | is to contain all the required parameters for audio configuration. At the | ||
| 72 | moment, such structure contains pointers to IEC-60958 channel status word | ||
| 73 | and CEA-861 audio infoframe structures. This should be enough to support | ||
| 74 | HDMI and DisplayPort, as both are based on CEA-861 and IEC-60958. | ||
| 75 | |||
| 76 | The audio_enable/disable, audio_config and audio_supported functions could be | ||
| 77 | implemented as functions that may sleep. Hence, they should not be called | ||
| 78 | while holding a spinlock or a readlock. | ||
| 79 | |||
| 80 | The audio_start/audio_stop function is intended to effectively start/stop audio | ||
| 81 | playback after the configuration has taken place. These functions are designed | ||
| 82 | to be used in an atomic context. Hence, audio_start should return quickly and be | ||
| 83 | called only after all the needed resources for audio playback (audio FIFOs, | ||
| 84 | DMA channels, companion chips, etc) have been enabled to begin data transfers. | ||
| 85 | audio_stop is designed to only stop the audio transfers. The resources used | ||
| 86 | for playback are released using audio_disable. | ||
| 87 | |||
| 88 | The enum omap_dss_audio_state may be used to help the implementations of | ||
| 89 | the interface to keep track of the audio state. The initial state is _DISABLED; | ||
| 90 | then, the state transitions to _CONFIGURED, and then, when it is ready to | ||
| 91 | play audio, to _ENABLED. The state _PLAYING is used when the audio is being | ||
| 92 | rendered. | ||
| 93 | |||
| 94 | |||
| 50 | Panel and controller drivers | 95 | Panel and controller drivers |
| 51 | ---------------------------- | 96 | ---------------------------- |
| 52 | 97 | ||
| @@ -156,6 +201,7 @@ timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw) | |||
| 156 | "pal" and "ntsc" | 201 | "pal" and "ntsc" |
| 157 | panel_name | 202 | panel_name |
| 158 | tear_elim Tearing elimination 0=off, 1=on | 203 | tear_elim Tearing elimination 0=off, 1=on |
| 204 | output_type Output type (video encoder only): "composite" or "svideo" | ||
| 159 | 205 | ||
| 160 | There are also some debugfs files at <debugfs>/omapdss/ which show information | 206 | There are also some debugfs files at <debugfs>/omapdss/ which show information |
| 161 | about clocks and registers. | 207 | about clocks and registers. |
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index 972983e392bc..656f8fc9addd 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c | |||
| @@ -237,25 +237,29 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { | |||
| 237 | #else | 237 | #else |
| 238 | /* Frame Buffer */ | 238 | /* Frame Buffer */ |
| 239 | static struct s3c_fb_pd_win nuri_fb_win0 = { | 239 | static struct s3c_fb_pd_win nuri_fb_win0 = { |
| 240 | .win_mode = { | ||
| 241 | .left_margin = 64, | ||
| 242 | .right_margin = 16, | ||
| 243 | .upper_margin = 64, | ||
| 244 | .lower_margin = 1, | ||
| 245 | .hsync_len = 48, | ||
| 246 | .vsync_len = 3, | ||
| 247 | .xres = 1024, | ||
| 248 | .yres = 600, | ||
| 249 | .refresh = 60, | ||
| 250 | }, | ||
| 251 | .max_bpp = 24, | 240 | .max_bpp = 24, |
| 252 | .default_bpp = 16, | 241 | .default_bpp = 16, |
| 242 | .xres = 1024, | ||
| 243 | .yres = 600, | ||
| 253 | .virtual_x = 1024, | 244 | .virtual_x = 1024, |
| 254 | .virtual_y = 2 * 600, | 245 | .virtual_y = 2 * 600, |
| 255 | }; | 246 | }; |
| 256 | 247 | ||
| 248 | static struct fb_videomode nuri_lcd_timing = { | ||
| 249 | .left_margin = 64, | ||
| 250 | .right_margin = 16, | ||
| 251 | .upper_margin = 64, | ||
| 252 | .lower_margin = 1, | ||
| 253 | .hsync_len = 48, | ||
| 254 | .vsync_len = 3, | ||
| 255 | .xres = 1024, | ||
| 256 | .yres = 600, | ||
| 257 | .refresh = 60, | ||
| 258 | }; | ||
| 259 | |||
| 257 | static struct s3c_fb_platdata nuri_fb_pdata __initdata = { | 260 | static struct s3c_fb_platdata nuri_fb_pdata __initdata = { |
| 258 | .win[0] = &nuri_fb_win0, | 261 | .win[0] = &nuri_fb_win0, |
| 262 | .vtiming = &nuri_lcd_timing, | ||
| 259 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | | 263 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | |
| 260 | VIDCON0_CLKSEL_LCD, | 264 | VIDCON0_CLKSEL_LCD, |
| 261 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | 265 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index a7f7fd567dde..f5572be9d7bf 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c | |||
| @@ -604,24 +604,28 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { | |||
| 604 | }; | 604 | }; |
| 605 | #else | 605 | #else |
| 606 | static struct s3c_fb_pd_win origen_fb_win0 = { | 606 | static struct s3c_fb_pd_win origen_fb_win0 = { |
| 607 | .win_mode = { | 607 | .xres = 1024, |
| 608 | .left_margin = 64, | 608 | .yres = 600, |
| 609 | .right_margin = 16, | ||
| 610 | .upper_margin = 64, | ||
| 611 | .lower_margin = 16, | ||
| 612 | .hsync_len = 48, | ||
| 613 | .vsync_len = 3, | ||
| 614 | .xres = 1024, | ||
| 615 | .yres = 600, | ||
| 616 | }, | ||
| 617 | .max_bpp = 32, | 609 | .max_bpp = 32, |
| 618 | .default_bpp = 24, | 610 | .default_bpp = 24, |
| 619 | .virtual_x = 1024, | 611 | .virtual_x = 1024, |
| 620 | .virtual_y = 2 * 600, | 612 | .virtual_y = 2 * 600, |
| 621 | }; | 613 | }; |
| 622 | 614 | ||
| 615 | static struct fb_videomode origen_lcd_timing = { | ||
| 616 | .left_margin = 64, | ||
| 617 | .right_margin = 16, | ||
| 618 | .upper_margin = 64, | ||
| 619 | .lower_margin = 16, | ||
| 620 | .hsync_len = 48, | ||
| 621 | .vsync_len = 3, | ||
| 622 | .xres = 1024, | ||
| 623 | .yres = 600, | ||
| 624 | }; | ||
| 625 | |||
| 623 | static struct s3c_fb_platdata origen_lcd_pdata __initdata = { | 626 | static struct s3c_fb_platdata origen_lcd_pdata __initdata = { |
| 624 | .win[0] = &origen_fb_win0, | 627 | .win[0] = &origen_fb_win0, |
| 628 | .vtiming = &origen_lcd_timing, | ||
| 625 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 629 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 626 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | | 630 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | |
| 627 | VIDCON1_INV_VCLK, | 631 | VIDCON1_INV_VCLK, |
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c index 70df1a0c2118..262e9e446a96 100644 --- a/arch/arm/mach-exynos/mach-smdkv310.c +++ b/arch/arm/mach-exynos/mach-smdkv310.c | |||
| @@ -178,22 +178,26 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { | |||
| 178 | }; | 178 | }; |
| 179 | #else | 179 | #else |
| 180 | static struct s3c_fb_pd_win smdkv310_fb_win0 = { | 180 | static struct s3c_fb_pd_win smdkv310_fb_win0 = { |
| 181 | .win_mode = { | 181 | .max_bpp = 32, |
| 182 | .left_margin = 13, | 182 | .default_bpp = 24, |
| 183 | .right_margin = 8, | 183 | .xres = 800, |
| 184 | .upper_margin = 7, | 184 | .yres = 480, |
| 185 | .lower_margin = 5, | 185 | }; |
| 186 | .hsync_len = 3, | 186 | |
| 187 | .vsync_len = 1, | 187 | static struct fb_videomode smdkv310_lcd_timing = { |
| 188 | .xres = 800, | 188 | .left_margin = 13, |
| 189 | .yres = 480, | 189 | .right_margin = 8, |
| 190 | }, | 190 | .upper_margin = 7, |
| 191 | .max_bpp = 32, | 191 | .lower_margin = 5, |
| 192 | .default_bpp = 24, | 192 | .hsync_len = 3, |
| 193 | .vsync_len = 1, | ||
| 194 | .xres = 800, | ||
| 195 | .yres = 480, | ||
| 193 | }; | 196 | }; |
| 194 | 197 | ||
| 195 | static struct s3c_fb_platdata smdkv310_lcd0_pdata __initdata = { | 198 | static struct s3c_fb_platdata smdkv310_lcd0_pdata __initdata = { |
| 196 | .win[0] = &smdkv310_fb_win0, | 199 | .win[0] = &smdkv310_fb_win0, |
| 200 | .vtiming = &smdkv310_lcd_timing, | ||
| 197 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 201 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 198 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | 202 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
| 199 | .setup_gpio = exynos4_fimd0_gpio_setup_24bpp, | 203 | .setup_gpio = exynos4_fimd0_gpio_setup_24bpp, |
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c index 083b44de9c10..cd92fa86ba41 100644 --- a/arch/arm/mach-exynos/mach-universal_c210.c +++ b/arch/arm/mach-exynos/mach-universal_c210.c | |||
| @@ -843,25 +843,29 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { | |||
| 843 | #else | 843 | #else |
| 844 | /* Frame Buffer */ | 844 | /* Frame Buffer */ |
| 845 | static struct s3c_fb_pd_win universal_fb_win0 = { | 845 | static struct s3c_fb_pd_win universal_fb_win0 = { |
| 846 | .win_mode = { | ||
| 847 | .left_margin = 16, | ||
| 848 | .right_margin = 16, | ||
| 849 | .upper_margin = 2, | ||
| 850 | .lower_margin = 28, | ||
| 851 | .hsync_len = 2, | ||
| 852 | .vsync_len = 1, | ||
| 853 | .xres = 480, | ||
| 854 | .yres = 800, | ||
| 855 | .refresh = 55, | ||
| 856 | }, | ||
| 857 | .max_bpp = 32, | 846 | .max_bpp = 32, |
| 858 | .default_bpp = 16, | 847 | .default_bpp = 16, |
| 848 | .xres = 480, | ||
| 849 | .yres = 800, | ||
| 859 | .virtual_x = 480, | 850 | .virtual_x = 480, |
| 860 | .virtual_y = 2 * 800, | 851 | .virtual_y = 2 * 800, |
| 861 | }; | 852 | }; |
| 862 | 853 | ||
| 854 | static struct fb_videomode universal_lcd_timing = { | ||
| 855 | .left_margin = 16, | ||
| 856 | .right_margin = 16, | ||
| 857 | .upper_margin = 2, | ||
| 858 | .lower_margin = 28, | ||
| 859 | .hsync_len = 2, | ||
| 860 | .vsync_len = 1, | ||
| 861 | .xres = 480, | ||
| 862 | .yres = 800, | ||
| 863 | .refresh = 55, | ||
| 864 | }; | ||
| 865 | |||
| 863 | static struct s3c_fb_platdata universal_lcd_pdata __initdata = { | 866 | static struct s3c_fb_platdata universal_lcd_pdata __initdata = { |
| 864 | .win[0] = &universal_fb_win0, | 867 | .win[0] = &universal_fb_win0, |
| 868 | .vtiming = &universal_lcd_timing, | ||
| 865 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | | 869 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | |
| 866 | VIDCON0_CLKSEL_LCD, | 870 | VIDCON0_CLKSEL_LCD, |
| 867 | .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN | 871 | .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN |
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index db5a88a36c63..54d49ddb9b81 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c | |||
| @@ -180,16 +180,133 @@ static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask) | |||
| 180 | omap4_dsi_mux_pads(dsi_id, 0); | 180 | omap4_dsi_mux_pads(dsi_id, 0); |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput) | ||
| 184 | { | ||
| 185 | return omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, tput); | ||
| 186 | } | ||
| 187 | |||
| 188 | static struct platform_device *create_dss_pdev(const char *pdev_name, | ||
| 189 | int pdev_id, const char *oh_name, void *pdata, int pdata_len, | ||
| 190 | struct platform_device *parent) | ||
| 191 | { | ||
| 192 | struct platform_device *pdev; | ||
| 193 | struct omap_device *od; | ||
| 194 | struct omap_hwmod *ohs[1]; | ||
| 195 | struct omap_hwmod *oh; | ||
| 196 | int r; | ||
| 197 | |||
| 198 | oh = omap_hwmod_lookup(oh_name); | ||
| 199 | if (!oh) { | ||
| 200 | pr_err("Could not look up %s\n", oh_name); | ||
| 201 | r = -ENODEV; | ||
| 202 | goto err; | ||
| 203 | } | ||
| 204 | |||
| 205 | pdev = platform_device_alloc(pdev_name, pdev_id); | ||
| 206 | if (!pdev) { | ||
| 207 | pr_err("Could not create pdev for %s\n", pdev_name); | ||
| 208 | r = -ENOMEM; | ||
| 209 | goto err; | ||
| 210 | } | ||
| 211 | |||
| 212 | if (parent != NULL) | ||
| 213 | pdev->dev.parent = &parent->dev; | ||
| 214 | |||
| 215 | if (pdev->id != -1) | ||
| 216 | dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); | ||
| 217 | else | ||
| 218 | dev_set_name(&pdev->dev, "%s", pdev->name); | ||
| 219 | |||
| 220 | ohs[0] = oh; | ||
| 221 | od = omap_device_alloc(pdev, ohs, 1, NULL, 0); | ||
| 222 | if (!od) { | ||
| 223 | pr_err("Could not alloc omap_device for %s\n", pdev_name); | ||
| 224 | r = -ENOMEM; | ||
| 225 | goto err; | ||
| 226 | } | ||
| 227 | |||
| 228 | r = platform_device_add_data(pdev, pdata, pdata_len); | ||
| 229 | if (r) { | ||
| 230 | pr_err("Could not set pdata for %s\n", pdev_name); | ||
| 231 | goto err; | ||
| 232 | } | ||
| 233 | |||
| 234 | r = omap_device_register(pdev); | ||
| 235 | if (r) { | ||
| 236 | pr_err("Could not register omap_device for %s\n", pdev_name); | ||
| 237 | goto err; | ||
| 238 | } | ||
| 239 | |||
| 240 | return pdev; | ||
| 241 | |||
| 242 | err: | ||
| 243 | return ERR_PTR(r); | ||
| 244 | } | ||
| 245 | |||
| 246 | static struct platform_device *create_simple_dss_pdev(const char *pdev_name, | ||
| 247 | int pdev_id, void *pdata, int pdata_len, | ||
| 248 | struct platform_device *parent) | ||
| 249 | { | ||
| 250 | struct platform_device *pdev; | ||
| 251 | int r; | ||
| 252 | |||
| 253 | pdev = platform_device_alloc(pdev_name, pdev_id); | ||
| 254 | if (!pdev) { | ||
| 255 | pr_err("Could not create pdev for %s\n", pdev_name); | ||
| 256 | r = -ENOMEM; | ||
| 257 | goto err; | ||
| 258 | } | ||
| 259 | |||
| 260 | if (parent != NULL) | ||
| 261 | pdev->dev.parent = &parent->dev; | ||
| 262 | |||
| 263 | if (pdev->id != -1) | ||
| 264 | dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); | ||
| 265 | else | ||
| 266 | dev_set_name(&pdev->dev, "%s", pdev->name); | ||
| 267 | |||
| 268 | r = platform_device_add_data(pdev, pdata, pdata_len); | ||
| 269 | if (r) { | ||
| 270 | pr_err("Could not set pdata for %s\n", pdev_name); | ||
| 271 | goto err; | ||
| 272 | } | ||
| 273 | |||
| 274 | r = omap_device_register(pdev); | ||
| 275 | if (r) { | ||
| 276 | pr_err("Could not register omap_device for %s\n", pdev_name); | ||
| 277 | goto err; | ||
| 278 | } | ||
| 279 | |||
| 280 | return pdev; | ||
| 281 | |||
| 282 | err: | ||
| 283 | return ERR_PTR(r); | ||
| 284 | } | ||
| 285 | |||
| 183 | int __init omap_display_init(struct omap_dss_board_info *board_data) | 286 | int __init omap_display_init(struct omap_dss_board_info *board_data) |
| 184 | { | 287 | { |
| 185 | int r = 0; | 288 | int r = 0; |
| 186 | struct omap_hwmod *oh; | ||
| 187 | struct platform_device *pdev; | 289 | struct platform_device *pdev; |
| 188 | int i, oh_count; | 290 | int i, oh_count; |
| 189 | struct omap_display_platform_data pdata; | ||
| 190 | const struct omap_dss_hwmod_data *curr_dss_hwmod; | 291 | const struct omap_dss_hwmod_data *curr_dss_hwmod; |
| 292 | struct platform_device *dss_pdev; | ||
| 293 | |||
| 294 | /* create omapdss device */ | ||
| 295 | |||
| 296 | board_data->dsi_enable_pads = omap_dsi_enable_pads; | ||
| 297 | board_data->dsi_disable_pads = omap_dsi_disable_pads; | ||
| 298 | board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count; | ||
| 299 | board_data->set_min_bus_tput = omap_dss_set_min_bus_tput; | ||
| 300 | |||
| 301 | omap_display_device.dev.platform_data = board_data; | ||
| 302 | |||
| 303 | r = platform_device_register(&omap_display_device); | ||
| 304 | if (r < 0) { | ||
| 305 | pr_err("Unable to register omapdss device\n"); | ||
| 306 | return r; | ||
| 307 | } | ||
| 191 | 308 | ||
| 192 | memset(&pdata, 0, sizeof(pdata)); | 309 | /* create devices for dss hwmods */ |
| 193 | 310 | ||
| 194 | if (cpu_is_omap24xx()) { | 311 | if (cpu_is_omap24xx()) { |
| 195 | curr_dss_hwmod = omap2_dss_hwmod_data; | 312 | curr_dss_hwmod = omap2_dss_hwmod_data; |
| @@ -202,39 +319,58 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) | |||
| 202 | oh_count = ARRAY_SIZE(omap4_dss_hwmod_data); | 319 | oh_count = ARRAY_SIZE(omap4_dss_hwmod_data); |
| 203 | } | 320 | } |
| 204 | 321 | ||
| 205 | if (board_data->dsi_enable_pads == NULL) | 322 | /* |
| 206 | board_data->dsi_enable_pads = omap_dsi_enable_pads; | 323 | * First create the pdev for dss_core, which is used as a parent device |
| 207 | if (board_data->dsi_disable_pads == NULL) | 324 | * by the other dss pdevs. Note: dss_core has to be the first item in |
| 208 | board_data->dsi_disable_pads = omap_dsi_disable_pads; | 325 | * the hwmod list. |
| 209 | 326 | */ | |
| 210 | pdata.board_data = board_data; | 327 | dss_pdev = create_dss_pdev(curr_dss_hwmod[0].dev_name, |
| 211 | pdata.board_data->get_context_loss_count = | 328 | curr_dss_hwmod[0].id, |
| 212 | omap_pm_get_dev_context_loss_count; | 329 | curr_dss_hwmod[0].oh_name, |
| 213 | 330 | board_data, sizeof(*board_data), | |
| 214 | for (i = 0; i < oh_count; i++) { | 331 | NULL); |
| 215 | oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name); | 332 | |
| 216 | if (!oh) { | 333 | if (IS_ERR(dss_pdev)) { |
| 217 | pr_err("Could not look up %s\n", | 334 | pr_err("Could not build omap_device for %s\n", |
| 218 | curr_dss_hwmod[i].oh_name); | 335 | curr_dss_hwmod[0].oh_name); |
| 219 | return -ENODEV; | 336 | |
| 337 | return PTR_ERR(dss_pdev); | ||
| 338 | } | ||
| 339 | |||
| 340 | for (i = 1; i < oh_count; i++) { | ||
| 341 | pdev = create_dss_pdev(curr_dss_hwmod[i].dev_name, | ||
| 342 | curr_dss_hwmod[i].id, | ||
| 343 | curr_dss_hwmod[i].oh_name, | ||
| 344 | board_data, sizeof(*board_data), | ||
| 345 | dss_pdev); | ||
| 346 | |||
| 347 | if (IS_ERR(pdev)) { | ||
| 348 | pr_err("Could not build omap_device for %s\n", | ||
| 349 | curr_dss_hwmod[i].oh_name); | ||
| 350 | |||
| 351 | return PTR_ERR(pdev); | ||
| 220 | } | 352 | } |
| 353 | } | ||
| 221 | 354 | ||
| 222 | pdev = omap_device_build(curr_dss_hwmod[i].dev_name, | 355 | /* Create devices for DPI and SDI */ |
| 223 | curr_dss_hwmod[i].id, oh, &pdata, | ||
| 224 | sizeof(struct omap_display_platform_data), | ||
| 225 | NULL, 0, 0); | ||
| 226 | 356 | ||
| 227 | if (WARN((IS_ERR(pdev)), "Could not build omap_device for %s\n", | 357 | pdev = create_simple_dss_pdev("omapdss_dpi", -1, |
| 228 | curr_dss_hwmod[i].oh_name)) | 358 | board_data, sizeof(*board_data), dss_pdev); |
| 229 | return -ENODEV; | 359 | if (IS_ERR(pdev)) { |
| 360 | pr_err("Could not build platform_device for omapdss_dpi\n"); | ||
| 361 | return PTR_ERR(pdev); | ||
| 230 | } | 362 | } |
| 231 | omap_display_device.dev.platform_data = board_data; | ||
| 232 | 363 | ||
| 233 | r = platform_device_register(&omap_display_device); | 364 | if (cpu_is_omap34xx()) { |
| 234 | if (r < 0) | 365 | pdev = create_simple_dss_pdev("omapdss_sdi", -1, |
| 235 | printk(KERN_ERR "Unable to register OMAP-Display device\n"); | 366 | board_data, sizeof(*board_data), dss_pdev); |
| 367 | if (IS_ERR(pdev)) { | ||
| 368 | pr_err("Could not build platform_device for omapdss_sdi\n"); | ||
| 369 | return PTR_ERR(pdev); | ||
| 370 | } | ||
| 371 | } | ||
| 236 | 372 | ||
| 237 | return r; | 373 | return 0; |
| 238 | } | 374 | } |
| 239 | 375 | ||
| 240 | static void dispc_disable_outputs(void) | 376 | static void dispc_disable_outputs(void) |
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c index 30a44f806e01..c3100a044fbe 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2416.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c | |||
| @@ -148,23 +148,25 @@ static struct s3c24xx_hsudc_platdata smdk2416_hsudc_platdata = { | |||
| 148 | 148 | ||
| 149 | static struct s3c_fb_pd_win smdk2416_fb_win[] = { | 149 | static struct s3c_fb_pd_win smdk2416_fb_win[] = { |
| 150 | [0] = { | 150 | [0] = { |
| 151 | /* think this is the same as the smdk6410 */ | ||
| 152 | .win_mode = { | ||
| 153 | .pixclock = 41094, | ||
| 154 | .left_margin = 8, | ||
| 155 | .right_margin = 13, | ||
| 156 | .upper_margin = 7, | ||
| 157 | .lower_margin = 5, | ||
| 158 | .hsync_len = 3, | ||
| 159 | .vsync_len = 1, | ||
| 160 | .xres = 800, | ||
| 161 | .yres = 480, | ||
| 162 | }, | ||
| 163 | .default_bpp = 16, | 151 | .default_bpp = 16, |
| 164 | .max_bpp = 32, | 152 | .max_bpp = 32, |
| 153 | .xres = 800, | ||
| 154 | .yres = 480, | ||
| 165 | }, | 155 | }, |
| 166 | }; | 156 | }; |
| 167 | 157 | ||
| 158 | static struct fb_videomode smdk2416_lcd_timing = { | ||
| 159 | .pixclock = 41094, | ||
| 160 | .left_margin = 8, | ||
| 161 | .right_margin = 13, | ||
| 162 | .upper_margin = 7, | ||
| 163 | .lower_margin = 5, | ||
| 164 | .hsync_len = 3, | ||
| 165 | .vsync_len = 1, | ||
| 166 | .xres = 800, | ||
| 167 | .yres = 480, | ||
| 168 | }; | ||
| 169 | |||
| 168 | static void s3c2416_fb_gpio_setup_24bpp(void) | 170 | static void s3c2416_fb_gpio_setup_24bpp(void) |
| 169 | { | 171 | { |
| 170 | unsigned int gpio; | 172 | unsigned int gpio; |
| @@ -187,6 +189,7 @@ static void s3c2416_fb_gpio_setup_24bpp(void) | |||
| 187 | 189 | ||
| 188 | static struct s3c_fb_platdata smdk2416_fb_platdata = { | 190 | static struct s3c_fb_platdata smdk2416_fb_platdata = { |
| 189 | .win[0] = &smdk2416_fb_win[0], | 191 | .win[0] = &smdk2416_fb_win[0], |
| 192 | .vtiming = &smdk2416_lcd_timing, | ||
| 190 | .setup_gpio = s3c2416_fb_gpio_setup_24bpp, | 193 | .setup_gpio = s3c2416_fb_gpio_setup_24bpp, |
| 191 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 194 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 192 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | 195 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c index 314df0518afd..ffa29ddfdfce 100644 --- a/arch/arm/mach-s3c64xx/mach-anw6410.c +++ b/arch/arm/mach-s3c64xx/mach-anw6410.c | |||
| @@ -134,24 +134,27 @@ static struct platform_device anw6410_lcd_powerdev = { | |||
| 134 | }; | 134 | }; |
| 135 | 135 | ||
| 136 | static struct s3c_fb_pd_win anw6410_fb_win0 = { | 136 | static struct s3c_fb_pd_win anw6410_fb_win0 = { |
| 137 | /* this is to ensure we use win0 */ | ||
| 138 | .win_mode = { | ||
| 139 | .left_margin = 8, | ||
| 140 | .right_margin = 13, | ||
| 141 | .upper_margin = 7, | ||
| 142 | .lower_margin = 5, | ||
| 143 | .hsync_len = 3, | ||
| 144 | .vsync_len = 1, | ||
| 145 | .xres = 800, | ||
| 146 | .yres = 480, | ||
| 147 | }, | ||
| 148 | .max_bpp = 32, | 137 | .max_bpp = 32, |
| 149 | .default_bpp = 16, | 138 | .default_bpp = 16, |
| 139 | .xres = 800, | ||
| 140 | .yres = 480, | ||
| 141 | }; | ||
| 142 | |||
| 143 | static struct fb_videomode anw6410_lcd_timing = { | ||
| 144 | .left_margin = 8, | ||
| 145 | .right_margin = 13, | ||
| 146 | .upper_margin = 7, | ||
| 147 | .lower_margin = 5, | ||
| 148 | .hsync_len = 3, | ||
| 149 | .vsync_len = 1, | ||
| 150 | .xres = 800, | ||
| 151 | .yres = 480, | ||
| 150 | }; | 152 | }; |
| 151 | 153 | ||
| 152 | /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ | 154 | /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ |
| 153 | static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = { | 155 | static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = { |
| 154 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, | 156 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, |
| 157 | .vtiming = &anw6410_lcd_timing, | ||
| 155 | .win[0] = &anw6410_fb_win0, | 158 | .win[0] = &anw6410_fb_win0, |
| 156 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 159 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 157 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | 160 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index 6b20a71d7dbf..d0c352d861f8 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c | |||
| @@ -151,26 +151,29 @@ static struct platform_device crag6410_lcd_powerdev = { | |||
| 151 | 151 | ||
| 152 | /* 640x480 URT */ | 152 | /* 640x480 URT */ |
| 153 | static struct s3c_fb_pd_win crag6410_fb_win0 = { | 153 | static struct s3c_fb_pd_win crag6410_fb_win0 = { |
| 154 | /* this is to ensure we use win0 */ | ||
| 155 | .win_mode = { | ||
| 156 | .left_margin = 150, | ||
| 157 | .right_margin = 80, | ||
| 158 | .upper_margin = 40, | ||
| 159 | .lower_margin = 5, | ||
| 160 | .hsync_len = 40, | ||
| 161 | .vsync_len = 5, | ||
| 162 | .xres = 640, | ||
| 163 | .yres = 480, | ||
| 164 | }, | ||
| 165 | .max_bpp = 32, | 154 | .max_bpp = 32, |
| 166 | .default_bpp = 16, | 155 | .default_bpp = 16, |
| 156 | .xres = 640, | ||
| 157 | .yres = 480, | ||
| 167 | .virtual_y = 480 * 2, | 158 | .virtual_y = 480 * 2, |
| 168 | .virtual_x = 640, | 159 | .virtual_x = 640, |
| 169 | }; | 160 | }; |
| 170 | 161 | ||
| 162 | static struct fb_videomode crag6410_lcd_timing = { | ||
| 163 | .left_margin = 150, | ||
| 164 | .right_margin = 80, | ||
| 165 | .upper_margin = 40, | ||
| 166 | .lower_margin = 5, | ||
| 167 | .hsync_len = 40, | ||
| 168 | .vsync_len = 5, | ||
| 169 | .xres = 640, | ||
| 170 | .yres = 480, | ||
| 171 | }; | ||
| 172 | |||
| 171 | /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ | 173 | /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ |
| 172 | static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = { | 174 | static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = { |
| 173 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, | 175 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, |
| 176 | .vtiming = &crag6410_lcd_timing, | ||
| 174 | .win[0] = &crag6410_fb_win0, | 177 | .win[0] = &crag6410_fb_win0, |
| 175 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 178 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 176 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | 179 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c index 1bf6b9da20fc..689088162f77 100644 --- a/arch/arm/mach-s3c64xx/mach-hmt.c +++ b/arch/arm/mach-s3c64xx/mach-hmt.c | |||
| @@ -129,23 +129,27 @@ static struct platform_device hmt_backlight_device = { | |||
| 129 | }; | 129 | }; |
| 130 | 130 | ||
| 131 | static struct s3c_fb_pd_win hmt_fb_win0 = { | 131 | static struct s3c_fb_pd_win hmt_fb_win0 = { |
| 132 | .win_mode = { | ||
| 133 | .left_margin = 8, | ||
| 134 | .right_margin = 13, | ||
| 135 | .upper_margin = 7, | ||
| 136 | .lower_margin = 5, | ||
| 137 | .hsync_len = 3, | ||
| 138 | .vsync_len = 1, | ||
| 139 | .xres = 800, | ||
| 140 | .yres = 480, | ||
| 141 | }, | ||
| 142 | .max_bpp = 32, | 132 | .max_bpp = 32, |
| 143 | .default_bpp = 16, | 133 | .default_bpp = 16, |
| 134 | .xres = 800, | ||
| 135 | .yres = 480, | ||
| 136 | }; | ||
| 137 | |||
| 138 | static struct fb_videomode hmt_lcd_timing = { | ||
| 139 | .left_margin = 8, | ||
| 140 | .right_margin = 13, | ||
| 141 | .upper_margin = 7, | ||
| 142 | .lower_margin = 5, | ||
| 143 | .hsync_len = 3, | ||
| 144 | .vsync_len = 1, | ||
| 145 | .xres = 800, | ||
| 146 | .yres = 480, | ||
| 144 | }; | 147 | }; |
| 145 | 148 | ||
| 146 | /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ | 149 | /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ |
| 147 | static struct s3c_fb_platdata hmt_lcd_pdata __initdata = { | 150 | static struct s3c_fb_platdata hmt_lcd_pdata __initdata = { |
| 148 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, | 151 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, |
| 152 | .vtiming = &hmt_lcd_timing, | ||
| 149 | .win[0] = &hmt_fb_win0, | 153 | .win[0] = &hmt_fb_win0, |
| 150 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 154 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 151 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | 155 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c index f8ea61ea3b33..5539a255a704 100644 --- a/arch/arm/mach-s3c64xx/mach-mini6410.c +++ b/arch/arm/mach-s3c64xx/mach-mini6410.c | |||
| @@ -140,41 +140,59 @@ static struct s3c2410_platform_nand mini6410_nand_info = { | |||
| 140 | .sets = mini6410_nand_sets, | 140 | .sets = mini6410_nand_sets, |
| 141 | }; | 141 | }; |
| 142 | 142 | ||
| 143 | static struct s3c_fb_pd_win mini6410_fb_win[] = { | 143 | static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = { |
| 144 | .max_bpp = 32, | ||
| 145 | .default_bpp = 16, | ||
| 146 | .xres = 480, | ||
| 147 | .yres = 272, | ||
| 148 | }; | ||
| 149 | |||
| 150 | static struct fb_videomode mini6410_lcd_type0_timing = { | ||
| 151 | /* 4.3" 480x272 */ | ||
| 152 | .left_margin = 3, | ||
| 153 | .right_margin = 2, | ||
| 154 | .upper_margin = 1, | ||
| 155 | .lower_margin = 1, | ||
| 156 | .hsync_len = 40, | ||
| 157 | .vsync_len = 1, | ||
| 158 | .xres = 480, | ||
| 159 | .yres = 272, | ||
| 160 | }; | ||
| 161 | |||
| 162 | static struct s3c_fb_pd_win mini6410_lcd_type1_fb_win = { | ||
| 163 | .max_bpp = 32, | ||
| 164 | .default_bpp = 16, | ||
| 165 | .xres = 800, | ||
| 166 | .yres = 480, | ||
| 167 | }; | ||
| 168 | |||
| 169 | static struct fb_videomode mini6410_lcd_type1_timing = { | ||
| 170 | /* 7.0" 800x480 */ | ||
| 171 | .left_margin = 8, | ||
| 172 | .right_margin = 13, | ||
| 173 | .upper_margin = 7, | ||
| 174 | .lower_margin = 5, | ||
| 175 | .hsync_len = 3, | ||
| 176 | .vsync_len = 1, | ||
| 177 | .xres = 800, | ||
| 178 | .yres = 480, | ||
| 179 | }; | ||
| 180 | |||
| 181 | static struct s3c_fb_platdata mini6410_lcd_pdata[] __initdata = { | ||
| 144 | { | 182 | { |
| 145 | .win_mode = { /* 4.3" 480x272 */ | 183 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, |
| 146 | .left_margin = 3, | 184 | .vtiming = &mini6410_lcd_type0_timing, |
| 147 | .right_margin = 2, | 185 | .win[0] = &mini6410_lcd_type0_fb_win, |
| 148 | .upper_margin = 1, | 186 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 149 | .lower_margin = 1, | 187 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
| 150 | .hsync_len = 40, | ||
| 151 | .vsync_len = 1, | ||
| 152 | .xres = 480, | ||
| 153 | .yres = 272, | ||
| 154 | }, | ||
| 155 | .max_bpp = 32, | ||
| 156 | .default_bpp = 16, | ||
| 157 | }, { | 188 | }, { |
| 158 | .win_mode = { /* 7.0" 800x480 */ | 189 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, |
| 159 | .left_margin = 8, | 190 | .vtiming = &mini6410_lcd_type1_timing, |
| 160 | .right_margin = 13, | 191 | .win[0] = &mini6410_lcd_type1_fb_win, |
| 161 | .upper_margin = 7, | 192 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 162 | .lower_margin = 5, | 193 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
| 163 | .hsync_len = 3, | ||
| 164 | .vsync_len = 1, | ||
| 165 | .xres = 800, | ||
| 166 | .yres = 480, | ||
| 167 | }, | ||
| 168 | .max_bpp = 32, | ||
| 169 | .default_bpp = 16, | ||
| 170 | }, | 194 | }, |
| 171 | }; | 195 | { }, |
| 172 | |||
| 173 | static struct s3c_fb_platdata mini6410_lcd_pdata __initdata = { | ||
| 174 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, | ||
| 175 | .win[0] = &mini6410_fb_win[0], | ||
| 176 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | ||
| 177 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | ||
| 178 | }; | 196 | }; |
| 179 | 197 | ||
| 180 | static void mini6410_lcd_power_set(struct plat_lcd_data *pd, | 198 | static void mini6410_lcd_power_set(struct plat_lcd_data *pd, |
| @@ -272,7 +290,7 @@ static void mini6410_parse_features( | |||
| 272 | "screen type already set\n", f); | 290 | "screen type already set\n", f); |
| 273 | } else { | 291 | } else { |
| 274 | int li = f - '0'; | 292 | int li = f - '0'; |
| 275 | if (li >= ARRAY_SIZE(mini6410_fb_win)) | 293 | if (li >= ARRAY_SIZE(mini6410_lcd_pdata)) |
| 276 | printk(KERN_INFO "MINI6410: '%c' out " | 294 | printk(KERN_INFO "MINI6410: '%c' out " |
| 277 | "of range LCD mode\n", f); | 295 | "of range LCD mode\n", f); |
| 278 | else { | 296 | else { |
| @@ -296,14 +314,12 @@ static void __init mini6410_machine_init(void) | |||
| 296 | /* Parse the feature string */ | 314 | /* Parse the feature string */ |
| 297 | mini6410_parse_features(&features, mini6410_features_str); | 315 | mini6410_parse_features(&features, mini6410_features_str); |
| 298 | 316 | ||
| 299 | mini6410_lcd_pdata.win[0] = &mini6410_fb_win[features.lcd_index]; | ||
| 300 | |||
| 301 | printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n", | 317 | printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n", |
| 302 | mini6410_lcd_pdata.win[0]->win_mode.xres, | 318 | mini6410_lcd_pdata[features.lcd_index].win[0]->xres, |
| 303 | mini6410_lcd_pdata.win[0]->win_mode.yres); | 319 | mini6410_lcd_pdata[features.lcd_index].win[0]->yres); |
| 304 | 320 | ||
| 305 | s3c_nand_set_platdata(&mini6410_nand_info); | 321 | s3c_nand_set_platdata(&mini6410_nand_info); |
| 306 | s3c_fb_set_platdata(&mini6410_lcd_pdata); | 322 | s3c_fb_set_platdata(&mini6410_lcd_pdata[features.lcd_index]); |
| 307 | s3c24xx_ts_set_platdata(NULL); | 323 | s3c24xx_ts_set_platdata(NULL); |
| 308 | 324 | ||
| 309 | /* configure nCS1 width to 16 bits */ | 325 | /* configure nCS1 width to 16 bits */ |
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c index b92d8e17d502..326b21604bc3 100644 --- a/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/arch/arm/mach-s3c64xx/mach-real6410.c | |||
| @@ -106,41 +106,57 @@ static struct platform_device real6410_device_eth = { | |||
| 106 | }, | 106 | }, |
| 107 | }; | 107 | }; |
| 108 | 108 | ||
| 109 | static struct s3c_fb_pd_win real6410_fb_win[] = { | 109 | static struct s3c_fb_pd_win real6410_lcd_type0_fb_win = { |
| 110 | .max_bpp = 32, | ||
| 111 | .default_bpp = 16, | ||
| 112 | .xres = 480, | ||
| 113 | .yres = 272, | ||
| 114 | }; | ||
| 115 | |||
| 116 | static struct fb_videomode real6410_lcd_type0_timing = { | ||
| 117 | /* 4.3" 480x272 */ | ||
| 118 | .left_margin = 3, | ||
| 119 | .right_margin = 2, | ||
| 120 | .upper_margin = 1, | ||
| 121 | .lower_margin = 1, | ||
| 122 | .hsync_len = 40, | ||
| 123 | .vsync_len = 1, | ||
| 124 | }; | ||
| 125 | |||
| 126 | static struct s3c_fb_pd_win real6410_lcd_type1_fb_win = { | ||
| 127 | .max_bpp = 32, | ||
| 128 | .default_bpp = 16, | ||
| 129 | .xres = 800, | ||
| 130 | .yres = 480, | ||
| 131 | }; | ||
| 132 | |||
| 133 | static struct fb_videomode real6410_lcd_type1_timing = { | ||
| 134 | /* 7.0" 800x480 */ | ||
| 135 | .left_margin = 8, | ||
| 136 | .right_margin = 13, | ||
| 137 | .upper_margin = 7, | ||
| 138 | .lower_margin = 5, | ||
| 139 | .hsync_len = 3, | ||
| 140 | .vsync_len = 1, | ||
| 141 | .xres = 800, | ||
| 142 | .yres = 480, | ||
| 143 | }; | ||
| 144 | |||
| 145 | static struct s3c_fb_platdata real6410_lcd_pdata[] __initdata = { | ||
| 110 | { | 146 | { |
| 111 | .win_mode = { /* 4.3" 480x272 */ | 147 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, |
| 112 | .left_margin = 3, | 148 | .vtiming = &real6410_lcd_type0_timing, |
| 113 | .right_margin = 2, | 149 | .win[0] = &real6410_lcd_type0_fb_win, |
| 114 | .upper_margin = 1, | 150 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 115 | .lower_margin = 1, | 151 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
| 116 | .hsync_len = 40, | ||
| 117 | .vsync_len = 1, | ||
| 118 | .xres = 480, | ||
| 119 | .yres = 272, | ||
| 120 | }, | ||
| 121 | .max_bpp = 32, | ||
| 122 | .default_bpp = 16, | ||
| 123 | }, { | 152 | }, { |
| 124 | .win_mode = { /* 7.0" 800x480 */ | 153 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, |
| 125 | .left_margin = 8, | 154 | .vtiming = &real6410_lcd_type1_timing, |
| 126 | .right_margin = 13, | 155 | .win[0] = &real6410_lcd_type1_fb_win, |
| 127 | .upper_margin = 7, | 156 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 128 | .lower_margin = 5, | 157 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
| 129 | .hsync_len = 3, | ||
| 130 | .vsync_len = 1, | ||
| 131 | .xres = 800, | ||
| 132 | .yres = 480, | ||
| 133 | }, | ||
| 134 | .max_bpp = 32, | ||
| 135 | .default_bpp = 16, | ||
| 136 | }, | 158 | }, |
| 137 | }; | 159 | { }, |
| 138 | |||
| 139 | static struct s3c_fb_platdata real6410_lcd_pdata __initdata = { | ||
| 140 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, | ||
| 141 | .win[0] = &real6410_fb_win[0], | ||
| 142 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | ||
| 143 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | ||
| 144 | }; | 160 | }; |
| 145 | 161 | ||
| 146 | static struct mtd_partition real6410_nand_part[] = { | 162 | static struct mtd_partition real6410_nand_part[] = { |
| @@ -253,7 +269,7 @@ static void real6410_parse_features( | |||
| 253 | "screen type already set\n", f); | 269 | "screen type already set\n", f); |
| 254 | } else { | 270 | } else { |
| 255 | int li = f - '0'; | 271 | int li = f - '0'; |
| 256 | if (li >= ARRAY_SIZE(real6410_fb_win)) | 272 | if (li >= ARRAY_SIZE(real6410_lcd_pdata)) |
| 257 | printk(KERN_INFO "REAL6410: '%c' out " | 273 | printk(KERN_INFO "REAL6410: '%c' out " |
| 258 | "of range LCD mode\n", f); | 274 | "of range LCD mode\n", f); |
| 259 | else { | 275 | else { |
| @@ -277,13 +293,11 @@ static void __init real6410_machine_init(void) | |||
| 277 | /* Parse the feature string */ | 293 | /* Parse the feature string */ |
| 278 | real6410_parse_features(&features, real6410_features_str); | 294 | real6410_parse_features(&features, real6410_features_str); |
| 279 | 295 | ||
| 280 | real6410_lcd_pdata.win[0] = &real6410_fb_win[features.lcd_index]; | ||
| 281 | |||
| 282 | printk(KERN_INFO "REAL6410: selected LCD display is %dx%d\n", | 296 | printk(KERN_INFO "REAL6410: selected LCD display is %dx%d\n", |
| 283 | real6410_lcd_pdata.win[0]->win_mode.xres, | 297 | real6410_lcd_pdata[features.lcd_index].win[0]->xres, |
| 284 | real6410_lcd_pdata.win[0]->win_mode.yres); | 298 | real6410_lcd_pdata[features.lcd_index].win[0]->yres); |
| 285 | 299 | ||
| 286 | s3c_fb_set_platdata(&real6410_lcd_pdata); | 300 | s3c_fb_set_platdata(&real6410_lcd_pdata[features.lcd_index]); |
| 287 | s3c_nand_set_platdata(&real6410_nand_info); | 301 | s3c_nand_set_platdata(&real6410_nand_info); |
| 288 | s3c24xx_ts_set_platdata(NULL); | 302 | s3c24xx_ts_set_platdata(NULL); |
| 289 | 303 | ||
diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c index c5021d0335c6..d6266d8b43c9 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq5.c +++ b/arch/arm/mach-s3c64xx/mach-smartq5.c | |||
| @@ -108,23 +108,27 @@ static struct platform_device smartq5_buttons_device = { | |||
| 108 | }; | 108 | }; |
| 109 | 109 | ||
| 110 | static struct s3c_fb_pd_win smartq5_fb_win0 = { | 110 | static struct s3c_fb_pd_win smartq5_fb_win0 = { |
| 111 | .win_mode = { | ||
| 112 | .left_margin = 216, | ||
| 113 | .right_margin = 40, | ||
| 114 | .upper_margin = 35, | ||
| 115 | .lower_margin = 10, | ||
| 116 | .hsync_len = 1, | ||
| 117 | .vsync_len = 1, | ||
| 118 | .xres = 800, | ||
| 119 | .yres = 480, | ||
| 120 | .refresh = 80, | ||
| 121 | }, | ||
| 122 | .max_bpp = 32, | 111 | .max_bpp = 32, |
| 123 | .default_bpp = 16, | 112 | .default_bpp = 16, |
| 113 | .xres = 800, | ||
| 114 | .yres = 480, | ||
| 115 | }; | ||
| 116 | |||
| 117 | static struct fb_videomode smartq5_lcd_timing = { | ||
| 118 | .left_margin = 216, | ||
| 119 | .right_margin = 40, | ||
| 120 | .upper_margin = 35, | ||
| 121 | .lower_margin = 10, | ||
| 122 | .hsync_len = 1, | ||
| 123 | .vsync_len = 1, | ||
| 124 | .xres = 800, | ||
| 125 | .yres = 480, | ||
| 126 | .refresh = 80, | ||
| 124 | }; | 127 | }; |
| 125 | 128 | ||
| 126 | static struct s3c_fb_platdata smartq5_lcd_pdata __initdata = { | 129 | static struct s3c_fb_platdata smartq5_lcd_pdata __initdata = { |
| 127 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, | 130 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, |
| 131 | .vtiming = &smartq5_lcd_timing, | ||
| 128 | .win[0] = &smartq5_fb_win0, | 132 | .win[0] = &smartq5_fb_win0, |
| 129 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 133 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 130 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | | 134 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | |
diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c index aa9072a4cbef..0957d2a980e1 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq7.c +++ b/arch/arm/mach-s3c64xx/mach-smartq7.c | |||
| @@ -124,23 +124,27 @@ static struct platform_device smartq7_buttons_device = { | |||
| 124 | }; | 124 | }; |
| 125 | 125 | ||
| 126 | static struct s3c_fb_pd_win smartq7_fb_win0 = { | 126 | static struct s3c_fb_pd_win smartq7_fb_win0 = { |
| 127 | .win_mode = { | ||
| 128 | .left_margin = 3, | ||
| 129 | .right_margin = 5, | ||
| 130 | .upper_margin = 1, | ||
| 131 | .lower_margin = 20, | ||
| 132 | .hsync_len = 10, | ||
| 133 | .vsync_len = 3, | ||
| 134 | .xres = 800, | ||
| 135 | .yres = 480, | ||
| 136 | .refresh = 80, | ||
| 137 | }, | ||
| 138 | .max_bpp = 32, | 127 | .max_bpp = 32, |
| 139 | .default_bpp = 16, | 128 | .default_bpp = 16, |
| 129 | .xres = 800, | ||
| 130 | .yres = 480, | ||
| 131 | }; | ||
| 132 | |||
| 133 | static struct fb_videomode smartq7_lcd_timing = { | ||
| 134 | .left_margin = 3, | ||
| 135 | .right_margin = 5, | ||
| 136 | .upper_margin = 1, | ||
| 137 | .lower_margin = 20, | ||
| 138 | .hsync_len = 10, | ||
| 139 | .vsync_len = 3, | ||
| 140 | .xres = 800, | ||
| 141 | .yres = 480, | ||
| 142 | .refresh = 80, | ||
| 140 | }; | 143 | }; |
| 141 | 144 | ||
| 142 | static struct s3c_fb_platdata smartq7_lcd_pdata __initdata = { | 145 | static struct s3c_fb_platdata smartq7_lcd_pdata __initdata = { |
| 143 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, | 146 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, |
| 147 | .vtiming = &smartq7_lcd_timing, | ||
| 144 | .win[0] = &smartq7_fb_win0, | 148 | .win[0] = &smartq7_fb_win0, |
| 145 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 149 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 146 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | | 150 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | |
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index d44319b09412..df3103d450e2 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c | |||
| @@ -146,26 +146,29 @@ static struct platform_device smdk6410_lcd_powerdev = { | |||
| 146 | }; | 146 | }; |
| 147 | 147 | ||
| 148 | static struct s3c_fb_pd_win smdk6410_fb_win0 = { | 148 | static struct s3c_fb_pd_win smdk6410_fb_win0 = { |
| 149 | /* this is to ensure we use win0 */ | ||
| 150 | .win_mode = { | ||
| 151 | .left_margin = 8, | ||
| 152 | .right_margin = 13, | ||
| 153 | .upper_margin = 7, | ||
| 154 | .lower_margin = 5, | ||
| 155 | .hsync_len = 3, | ||
| 156 | .vsync_len = 1, | ||
| 157 | .xres = 800, | ||
| 158 | .yres = 480, | ||
| 159 | }, | ||
| 160 | .max_bpp = 32, | 149 | .max_bpp = 32, |
| 161 | .default_bpp = 16, | 150 | .default_bpp = 16, |
| 151 | .xres = 800, | ||
| 152 | .yres = 480, | ||
| 162 | .virtual_y = 480 * 2, | 153 | .virtual_y = 480 * 2, |
| 163 | .virtual_x = 800, | 154 | .virtual_x = 800, |
| 164 | }; | 155 | }; |
| 165 | 156 | ||
| 157 | static struct fb_videomode smdk6410_lcd_timing = { | ||
| 158 | .left_margin = 8, | ||
| 159 | .right_margin = 13, | ||
| 160 | .upper_margin = 7, | ||
| 161 | .lower_margin = 5, | ||
| 162 | .hsync_len = 3, | ||
| 163 | .vsync_len = 1, | ||
| 164 | .xres = 800, | ||
| 165 | .yres = 480, | ||
| 166 | }; | ||
| 167 | |||
| 166 | /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ | 168 | /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ |
| 167 | static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = { | 169 | static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = { |
| 168 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, | 170 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, |
| 171 | .vtiming = &smdk6410_lcd_timing, | ||
| 169 | .win[0] = &smdk6410_fb_win0, | 172 | .win[0] = &smdk6410_fb_win0, |
| 170 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 173 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 171 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | 174 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c index a40e325d62c8..92fefad505cc 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6440.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c | |||
| @@ -103,22 +103,26 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = { | |||
| 103 | 103 | ||
| 104 | /* Frame Buffer */ | 104 | /* Frame Buffer */ |
| 105 | static struct s3c_fb_pd_win smdk6440_fb_win0 = { | 105 | static struct s3c_fb_pd_win smdk6440_fb_win0 = { |
| 106 | .win_mode = { | ||
| 107 | .left_margin = 8, | ||
| 108 | .right_margin = 13, | ||
| 109 | .upper_margin = 7, | ||
| 110 | .lower_margin = 5, | ||
| 111 | .hsync_len = 3, | ||
| 112 | .vsync_len = 1, | ||
| 113 | .xres = 800, | ||
| 114 | .yres = 480, | ||
| 115 | }, | ||
| 116 | .max_bpp = 32, | 106 | .max_bpp = 32, |
| 117 | .default_bpp = 24, | 107 | .default_bpp = 24, |
| 108 | .xres = 800, | ||
| 109 | .yres = 480, | ||
| 110 | }; | ||
| 111 | |||
| 112 | static struct fb_videomode smdk6440_lcd_timing = { | ||
| 113 | .left_margin = 8, | ||
| 114 | .right_margin = 13, | ||
| 115 | .upper_margin = 7, | ||
| 116 | .lower_margin = 5, | ||
| 117 | .hsync_len = 3, | ||
| 118 | .vsync_len = 1, | ||
| 119 | .xres = 800, | ||
| 120 | .yres = 480, | ||
| 118 | }; | 121 | }; |
| 119 | 122 | ||
| 120 | static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = { | 123 | static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = { |
| 121 | .win[0] = &smdk6440_fb_win0, | 124 | .win[0] = &smdk6440_fb_win0, |
| 125 | .vtiming = &smdk6440_lcd_timing, | ||
| 122 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 126 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 123 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | 127 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
| 124 | .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, | 128 | .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, |
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c index efb69e2f2afe..e2335ecf6eae 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6450.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c | |||
| @@ -121,22 +121,26 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = { | |||
| 121 | 121 | ||
| 122 | /* Frame Buffer */ | 122 | /* Frame Buffer */ |
| 123 | static struct s3c_fb_pd_win smdk6450_fb_win0 = { | 123 | static struct s3c_fb_pd_win smdk6450_fb_win0 = { |
| 124 | .win_mode = { | ||
| 125 | .left_margin = 8, | ||
| 126 | .right_margin = 13, | ||
| 127 | .upper_margin = 7, | ||
| 128 | .lower_margin = 5, | ||
| 129 | .hsync_len = 3, | ||
| 130 | .vsync_len = 1, | ||
| 131 | .xres = 800, | ||
| 132 | .yres = 480, | ||
| 133 | }, | ||
| 134 | .max_bpp = 32, | 124 | .max_bpp = 32, |
| 135 | .default_bpp = 24, | 125 | .default_bpp = 24, |
| 126 | .xres = 800, | ||
| 127 | .yres = 480, | ||
| 128 | }; | ||
| 129 | |||
| 130 | static struct fb_videomode smdk6450_lcd_timing = { | ||
| 131 | .left_margin = 8, | ||
| 132 | .right_margin = 13, | ||
| 133 | .upper_margin = 7, | ||
| 134 | .lower_margin = 5, | ||
| 135 | .hsync_len = 3, | ||
| 136 | .vsync_len = 1, | ||
| 137 | .xres = 800, | ||
| 138 | .yres = 480, | ||
| 136 | }; | 139 | }; |
| 137 | 140 | ||
| 138 | static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = { | 141 | static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = { |
| 139 | .win[0] = &smdk6450_fb_win0, | 142 | .win[0] = &smdk6450_fb_win0, |
| 143 | .vtiming = &smdk6450_lcd_timing, | ||
| 140 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 144 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 141 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | 145 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
| 142 | .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, | 146 | .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, |
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c index 674d22992f3c..0c3ae38d27ca 100644 --- a/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c | |||
| @@ -136,24 +136,27 @@ static struct platform_device smdkc100_lcd_powerdev = { | |||
| 136 | 136 | ||
| 137 | /* Frame Buffer */ | 137 | /* Frame Buffer */ |
| 138 | static struct s3c_fb_pd_win smdkc100_fb_win0 = { | 138 | static struct s3c_fb_pd_win smdkc100_fb_win0 = { |
| 139 | /* this is to ensure we use win0 */ | ||
| 140 | .win_mode = { | ||
| 141 | .left_margin = 8, | ||
| 142 | .right_margin = 13, | ||
| 143 | .upper_margin = 7, | ||
| 144 | .lower_margin = 5, | ||
| 145 | .hsync_len = 3, | ||
| 146 | .vsync_len = 1, | ||
| 147 | .xres = 800, | ||
| 148 | .yres = 480, | ||
| 149 | .refresh = 80, | ||
| 150 | }, | ||
| 151 | .max_bpp = 32, | 139 | .max_bpp = 32, |
| 152 | .default_bpp = 16, | 140 | .default_bpp = 16, |
| 141 | .xres = 800, | ||
| 142 | .yres = 480, | ||
| 143 | }; | ||
| 144 | |||
| 145 | static struct fb_videomode smdkc100_lcd_timing = { | ||
| 146 | .left_margin = 8, | ||
| 147 | .right_margin = 13, | ||
| 148 | .upper_margin = 7, | ||
| 149 | .lower_margin = 5, | ||
| 150 | .hsync_len = 3, | ||
| 151 | .vsync_len = 1, | ||
| 152 | .xres = 800, | ||
| 153 | .yres = 480, | ||
| 154 | .refresh = 80, | ||
| 153 | }; | 155 | }; |
| 154 | 156 | ||
| 155 | static struct s3c_fb_platdata smdkc100_lcd_pdata __initdata = { | 157 | static struct s3c_fb_platdata smdkc100_lcd_pdata __initdata = { |
| 156 | .win[0] = &smdkc100_fb_win0, | 158 | .win[0] = &smdkc100_fb_win0, |
| 159 | .vtiming = &smdkc100_lcd_timing, | ||
| 157 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 160 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 158 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | 161 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
| 159 | .setup_gpio = s5pc100_fb_gpio_setup_24bpp, | 162 | .setup_gpio = s5pc100_fb_gpio_setup_24bpp, |
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 48d018f2332b..af528f9e97f9 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c | |||
| @@ -96,38 +96,34 @@ static struct s3c2410_uartcfg aquila_uartcfgs[] __initdata = { | |||
| 96 | 96 | ||
| 97 | /* Frame Buffer */ | 97 | /* Frame Buffer */ |
| 98 | static struct s3c_fb_pd_win aquila_fb_win0 = { | 98 | static struct s3c_fb_pd_win aquila_fb_win0 = { |
| 99 | .win_mode = { | ||
| 100 | .left_margin = 16, | ||
| 101 | .right_margin = 16, | ||
| 102 | .upper_margin = 3, | ||
| 103 | .lower_margin = 28, | ||
| 104 | .hsync_len = 2, | ||
| 105 | .vsync_len = 2, | ||
| 106 | .xres = 480, | ||
| 107 | .yres = 800, | ||
| 108 | }, | ||
| 109 | .max_bpp = 32, | 99 | .max_bpp = 32, |
| 110 | .default_bpp = 16, | 100 | .default_bpp = 16, |
| 101 | .xres = 480, | ||
| 102 | .yres = 800, | ||
| 111 | }; | 103 | }; |
| 112 | 104 | ||
| 113 | static struct s3c_fb_pd_win aquila_fb_win1 = { | 105 | static struct s3c_fb_pd_win aquila_fb_win1 = { |
| 114 | .win_mode = { | ||
| 115 | .left_margin = 16, | ||
| 116 | .right_margin = 16, | ||
| 117 | .upper_margin = 3, | ||
| 118 | .lower_margin = 28, | ||
| 119 | .hsync_len = 2, | ||
| 120 | .vsync_len = 2, | ||
| 121 | .xres = 480, | ||
| 122 | .yres = 800, | ||
| 123 | }, | ||
| 124 | .max_bpp = 32, | 106 | .max_bpp = 32, |
| 125 | .default_bpp = 16, | 107 | .default_bpp = 16, |
| 108 | .xres = 480, | ||
| 109 | .yres = 800, | ||
| 110 | }; | ||
| 111 | |||
| 112 | static struct fb_videomode aquila_lcd_timing = { | ||
| 113 | .left_margin = 16, | ||
| 114 | .right_margin = 16, | ||
| 115 | .upper_margin = 3, | ||
| 116 | .lower_margin = 28, | ||
| 117 | .hsync_len = 2, | ||
| 118 | .vsync_len = 2, | ||
| 119 | .xres = 480, | ||
| 120 | .yres = 800, | ||
| 126 | }; | 121 | }; |
| 127 | 122 | ||
| 128 | static struct s3c_fb_platdata aquila_lcd_pdata __initdata = { | 123 | static struct s3c_fb_platdata aquila_lcd_pdata __initdata = { |
| 129 | .win[0] = &aquila_fb_win0, | 124 | .win[0] = &aquila_fb_win0, |
| 130 | .win[1] = &aquila_fb_win1, | 125 | .win[1] = &aquila_fb_win1, |
| 126 | .vtiming = &aquila_lcd_timing, | ||
| 131 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 127 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 132 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | | 128 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | |
| 133 | VIDCON1_INV_VCLK | VIDCON1_INV_VDEN, | 129 | VIDCON1_INV_VCLK | VIDCON1_INV_VDEN, |
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index f20a97c8e411..bf5087c2b7fe 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c | |||
| @@ -107,25 +107,29 @@ static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = { | |||
| 107 | 107 | ||
| 108 | /* Frame Buffer */ | 108 | /* Frame Buffer */ |
| 109 | static struct s3c_fb_pd_win goni_fb_win0 = { | 109 | static struct s3c_fb_pd_win goni_fb_win0 = { |
| 110 | .win_mode = { | ||
| 111 | .left_margin = 16, | ||
| 112 | .right_margin = 16, | ||
| 113 | .upper_margin = 2, | ||
| 114 | .lower_margin = 28, | ||
| 115 | .hsync_len = 2, | ||
| 116 | .vsync_len = 1, | ||
| 117 | .xres = 480, | ||
| 118 | .yres = 800, | ||
| 119 | .refresh = 55, | ||
| 120 | }, | ||
| 121 | .max_bpp = 32, | 110 | .max_bpp = 32, |
| 122 | .default_bpp = 16, | 111 | .default_bpp = 16, |
| 112 | .xres = 480, | ||
| 113 | .yres = 800, | ||
| 123 | .virtual_x = 480, | 114 | .virtual_x = 480, |
| 124 | .virtual_y = 2 * 800, | 115 | .virtual_y = 2 * 800, |
| 125 | }; | 116 | }; |
| 126 | 117 | ||
| 118 | static struct fb_videomode goni_lcd_timing = { | ||
| 119 | .left_margin = 16, | ||
| 120 | .right_margin = 16, | ||
| 121 | .upper_margin = 2, | ||
| 122 | .lower_margin = 28, | ||
| 123 | .hsync_len = 2, | ||
| 124 | .vsync_len = 1, | ||
| 125 | .xres = 480, | ||
| 126 | .yres = 800, | ||
| 127 | .refresh = 55, | ||
| 128 | }; | ||
| 129 | |||
| 127 | static struct s3c_fb_platdata goni_lcd_pdata __initdata = { | 130 | static struct s3c_fb_platdata goni_lcd_pdata __initdata = { |
| 128 | .win[0] = &goni_fb_win0, | 131 | .win[0] = &goni_fb_win0, |
| 132 | .vtiming = &goni_lcd_timing, | ||
| 129 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | | 133 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | |
| 130 | VIDCON0_CLKSEL_LCD, | 134 | VIDCON0_CLKSEL_LCD, |
| 131 | .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN | 135 | .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN |
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index fa1b61209fd9..0d7ddec88eb7 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c | |||
| @@ -178,22 +178,26 @@ static struct platform_device smdkv210_lcd_lte480wv = { | |||
| 178 | }; | 178 | }; |
| 179 | 179 | ||
| 180 | static struct s3c_fb_pd_win smdkv210_fb_win0 = { | 180 | static struct s3c_fb_pd_win smdkv210_fb_win0 = { |
| 181 | .win_mode = { | ||
| 182 | .left_margin = 13, | ||
| 183 | .right_margin = 8, | ||
| 184 | .upper_margin = 7, | ||
| 185 | .lower_margin = 5, | ||
| 186 | .hsync_len = 3, | ||
| 187 | .vsync_len = 1, | ||
| 188 | .xres = 800, | ||
| 189 | .yres = 480, | ||
| 190 | }, | ||
| 191 | .max_bpp = 32, | 181 | .max_bpp = 32, |
| 192 | .default_bpp = 24, | 182 | .default_bpp = 24, |
| 183 | .xres = 800, | ||
| 184 | .yres = 480, | ||
| 185 | }; | ||
| 186 | |||
| 187 | static struct fb_videomode smdkv210_lcd_timing = { | ||
| 188 | .left_margin = 13, | ||
| 189 | .right_margin = 8, | ||
| 190 | .upper_margin = 7, | ||
| 191 | .lower_margin = 5, | ||
| 192 | .hsync_len = 3, | ||
| 193 | .vsync_len = 1, | ||
| 194 | .xres = 800, | ||
| 195 | .yres = 480, | ||
| 193 | }; | 196 | }; |
| 194 | 197 | ||
| 195 | static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = { | 198 | static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = { |
| 196 | .win[0] = &smdkv210_fb_win0, | 199 | .win[0] = &smdkv210_fb_win0, |
| 200 | .vtiming = &smdkv210_lcd_timing, | ||
| 197 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | 201 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, |
| 198 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | 202 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, |
| 199 | .setup_gpio = s5pv210_fb_gpio_setup_24bpp, | 203 | .setup_gpio = s5pv210_fb_gpio_setup_24bpp, |
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h index 0fedf47fa502..536002ff2ab8 100644 --- a/arch/arm/plat-samsung/include/plat/fb.h +++ b/arch/arm/plat-samsung/include/plat/fb.h | |||
| @@ -24,15 +24,16 @@ | |||
| 24 | 24 | ||
| 25 | /** | 25 | /** |
| 26 | * struct s3c_fb_pd_win - per window setup data | 26 | * struct s3c_fb_pd_win - per window setup data |
| 27 | * @win_mode: The display parameters to initialise (not for window 0) | 27 | * @xres : The window X size. |
| 28 | * @yres : The window Y size. | ||
| 28 | * @virtual_x: The virtual X size. | 29 | * @virtual_x: The virtual X size. |
| 29 | * @virtual_y: The virtual Y size. | 30 | * @virtual_y: The virtual Y size. |
| 30 | */ | 31 | */ |
| 31 | struct s3c_fb_pd_win { | 32 | struct s3c_fb_pd_win { |
| 32 | struct fb_videomode win_mode; | ||
| 33 | |||
| 34 | unsigned short default_bpp; | 33 | unsigned short default_bpp; |
| 35 | unsigned short max_bpp; | 34 | unsigned short max_bpp; |
| 35 | unsigned short xres; | ||
| 36 | unsigned short yres; | ||
| 36 | unsigned short virtual_x; | 37 | unsigned short virtual_x; |
| 37 | unsigned short virtual_y; | 38 | unsigned short virtual_y; |
| 38 | }; | 39 | }; |
| @@ -45,6 +46,7 @@ struct s3c_fb_pd_win { | |||
| 45 | * @default_win: default window layer number to be used for UI layer. | 46 | * @default_win: default window layer number to be used for UI layer. |
| 46 | * @vidcon0: The base vidcon0 values to control the panel data format. | 47 | * @vidcon0: The base vidcon0 values to control the panel data format. |
| 47 | * @vidcon1: The base vidcon1 values to control the panel data output. | 48 | * @vidcon1: The base vidcon1 values to control the panel data output. |
| 49 | * @vtiming: Video timing when connected to a RGB type panel. | ||
| 48 | * @win: The setup data for each hardware window, or NULL for unused. | 50 | * @win: The setup data for each hardware window, or NULL for unused. |
| 49 | * @display_mode: The LCD output display mode. | 51 | * @display_mode: The LCD output display mode. |
| 50 | * | 52 | * |
| @@ -58,8 +60,7 @@ struct s3c_fb_platdata { | |||
| 58 | void (*setup_gpio)(void); | 60 | void (*setup_gpio)(void); |
| 59 | 61 | ||
| 60 | struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; | 62 | struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; |
| 61 | 63 | struct fb_videomode *vtiming; | |
| 62 | u32 default_win; | ||
| 63 | 64 | ||
| 64 | u32 vidcon0; | 65 | u32 vidcon0; |
| 65 | u32 vidcon1; | 66 | u32 vidcon1; |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index a290be51a1f4..0217f7415ef5 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -2210,7 +2210,7 @@ config FB_XILINX | |||
| 2210 | 2210 | ||
| 2211 | config FB_COBALT | 2211 | config FB_COBALT |
| 2212 | tristate "Cobalt server LCD frame buffer support" | 2212 | tristate "Cobalt server LCD frame buffer support" |
| 2213 | depends on FB && MIPS_COBALT | 2213 | depends on FB && (MIPS_COBALT || MIPS_SEAD3) |
| 2214 | 2214 | ||
| 2215 | config FB_SH7760 | 2215 | config FB_SH7760 |
| 2216 | bool "SH7760/SH7763/SH7720/SH7721 LCDC support" | 2216 | bool "SH7760/SH7763/SH7720/SH7721 LCDC support" |
| @@ -2382,6 +2382,39 @@ config FB_BROADSHEET | |||
| 2382 | and could also have been called by other names when coupled with | 2382 | and could also have been called by other names when coupled with |
| 2383 | a bridge adapter. | 2383 | a bridge adapter. |
| 2384 | 2384 | ||
| 2385 | config FB_AUO_K190X | ||
| 2386 | tristate "AUO-K190X EPD controller support" | ||
| 2387 | depends on FB | ||
| 2388 | select FB_SYS_FILLRECT | ||
| 2389 | select FB_SYS_COPYAREA | ||
| 2390 | select FB_SYS_IMAGEBLIT | ||
| 2391 | select FB_SYS_FOPS | ||
| 2392 | select FB_DEFERRED_IO | ||
| 2393 | help | ||
| 2394 | Provides support for epaper controllers from the K190X series | ||
| 2395 | of AUO. These controllers can be used to drive epaper displays | ||
| 2396 | from Sipix. | ||
| 2397 | |||
| 2398 | This option enables the common support, shared by the individual | ||
| 2399 | controller drivers. You will also have to enable the driver | ||
| 2400 | for the controller type used in your device. | ||
| 2401 | |||
| 2402 | config FB_AUO_K1900 | ||
| 2403 | tristate "AUO-K1900 EPD controller support" | ||
| 2404 | depends on FB && FB_AUO_K190X | ||
| 2405 | help | ||
| 2406 | This driver implements support for the AUO K1900 epd-controller. | ||
| 2407 | This controller can drive Sipix epaper displays but can only do | ||
| 2408 | serial updates, reducing the number of possible frames per second. | ||
| 2409 | |||
| 2410 | config FB_AUO_K1901 | ||
| 2411 | tristate "AUO-K1901 EPD controller support" | ||
| 2412 | depends on FB && FB_AUO_K190X | ||
| 2413 | help | ||
| 2414 | This driver implements support for the AUO K1901 epd-controller. | ||
| 2415 | This controller can drive Sipix epaper displays and supports | ||
| 2416 | concurrent updates, making higher frames per second possible. | ||
| 2417 | |||
| 2385 | config FB_JZ4740 | 2418 | config FB_JZ4740 |
| 2386 | tristate "JZ4740 LCD framebuffer support" | 2419 | tristate "JZ4740 LCD framebuffer support" |
| 2387 | depends on FB && MACH_JZ4740 | 2420 | depends on FB && MACH_JZ4740 |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 9356add945b3..ee8dafb69e36 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
| @@ -118,6 +118,9 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o | |||
| 118 | obj-$(CONFIG_FB_MAXINE) += maxinefb.o | 118 | obj-$(CONFIG_FB_MAXINE) += maxinefb.o |
| 119 | obj-$(CONFIG_FB_METRONOME) += metronomefb.o | 119 | obj-$(CONFIG_FB_METRONOME) += metronomefb.o |
| 120 | obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o | 120 | obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o |
| 121 | obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o | ||
| 122 | obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o | ||
| 123 | obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o | ||
| 121 | obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o | 124 | obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o |
| 122 | obj-$(CONFIG_FB_SH7760) += sh7760fb.o | 125 | obj-$(CONFIG_FB_SH7760) += sh7760fb.o |
| 123 | obj-$(CONFIG_FB_IMX) += imxfb.o | 126 | obj-$(CONFIG_FB_IMX) += imxfb.o |
diff --git a/drivers/video/auo_k1900fb.c b/drivers/video/auo_k1900fb.c new file mode 100644 index 000000000000..c36cf961dcb2 --- /dev/null +++ b/drivers/video/auo_k1900fb.c | |||
| @@ -0,0 +1,198 @@ | |||
| 1 | /* | ||
| 2 | * auok190xfb.c -- FB driver for AUO-K1900 controllers | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011, 2012 Heiko Stuebner <heiko@sntech.de> | ||
| 5 | * | ||
| 6 | * based on broadsheetfb.c | ||
| 7 | * | ||
| 8 | * Copyright (C) 2008, Jaya Kumar | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. | ||
| 15 | * | ||
| 16 | * This driver is written to be used with the AUO-K1900 display controller. | ||
| 17 | * | ||
| 18 | * It is intended to be architecture independent. A board specific driver | ||
| 19 | * must be used to perform all the physical IO interactions. | ||
| 20 | * | ||
| 21 | * The controller supports different update modes: | ||
| 22 | * mode0+1 16 step gray (4bit) | ||
| 23 | * mode2 4 step gray (2bit) - FIXME: add strange refresh | ||
| 24 | * mode3 2 step gray (1bit) - FIXME: add strange refresh | ||
| 25 | * mode4 handwriting mode (strange behaviour) | ||
| 26 | * mode5 automatic selection of update mode | ||
| 27 | */ | ||
| 28 | |||
| 29 | #include <linux/module.h> | ||
| 30 | #include <linux/kernel.h> | ||
| 31 | #include <linux/errno.h> | ||
| 32 | #include <linux/string.h> | ||
| 33 | #include <linux/mm.h> | ||
| 34 | #include <linux/slab.h> | ||
| 35 | #include <linux/delay.h> | ||
| 36 | #include <linux/interrupt.h> | ||
| 37 | #include <linux/fb.h> | ||
| 38 | #include <linux/init.h> | ||
| 39 | #include <linux/platform_device.h> | ||
| 40 | #include <linux/list.h> | ||
| 41 | #include <linux/firmware.h> | ||
| 42 | #include <linux/gpio.h> | ||
| 43 | #include <linux/pm_runtime.h> | ||
| 44 | |||
| 45 | #include <video/auo_k190xfb.h> | ||
| 46 | |||
| 47 | #include "auo_k190x.h" | ||
| 48 | |||
| 49 | /* | ||
| 50 | * AUO-K1900 specific commands | ||
| 51 | */ | ||
| 52 | |||
| 53 | #define AUOK1900_CMD_PARTIALDISP 0x1001 | ||
| 54 | #define AUOK1900_CMD_ROTATION 0x1006 | ||
| 55 | #define AUOK1900_CMD_LUT_STOP 0x1009 | ||
| 56 | |||
| 57 | #define AUOK1900_INIT_TEMP_AVERAGE (1 << 13) | ||
| 58 | #define AUOK1900_INIT_ROTATE(_x) ((_x & 0x3) << 10) | ||
| 59 | #define AUOK1900_INIT_RESOLUTION(_res) ((_res & 0x7) << 2) | ||
| 60 | |||
| 61 | static void auok1900_init(struct auok190xfb_par *par) | ||
| 62 | { | ||
| 63 | struct auok190x_board *board = par->board; | ||
| 64 | u16 init_param = 0; | ||
| 65 | |||
| 66 | init_param |= AUOK1900_INIT_TEMP_AVERAGE; | ||
| 67 | init_param |= AUOK1900_INIT_ROTATE(par->rotation); | ||
| 68 | init_param |= AUOK190X_INIT_INVERSE_WHITE; | ||
| 69 | init_param |= AUOK190X_INIT_FORMAT0; | ||
| 70 | init_param |= AUOK1900_INIT_RESOLUTION(par->resolution); | ||
| 71 | init_param |= AUOK190X_INIT_SHIFT_RIGHT; | ||
| 72 | |||
| 73 | auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param); | ||
| 74 | |||
| 75 | /* let the controller finish */ | ||
| 76 | board->wait_for_rdy(par); | ||
| 77 | } | ||
| 78 | |||
| 79 | static void auok1900_update_region(struct auok190xfb_par *par, int mode, | ||
| 80 | u16 y1, u16 y2) | ||
| 81 | { | ||
| 82 | struct device *dev = par->info->device; | ||
| 83 | unsigned char *buf = (unsigned char *)par->info->screen_base; | ||
| 84 | int xres = par->info->var.xres; | ||
| 85 | u16 args[4]; | ||
| 86 | |||
| 87 | pm_runtime_get_sync(dev); | ||
| 88 | |||
| 89 | mutex_lock(&(par->io_lock)); | ||
| 90 | |||
| 91 | /* y1 and y2 must be a multiple of 2 so drop the lowest bit */ | ||
| 92 | y1 &= 0xfffe; | ||
| 93 | y2 &= 0xfffe; | ||
| 94 | |||
| 95 | dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n", | ||
| 96 | 1, y1+1, xres, y2-y1, mode); | ||
| 97 | |||
| 98 | /* to FIX handle different partial update modes */ | ||
| 99 | args[0] = mode | 1; | ||
| 100 | args[1] = y1 + 1; | ||
| 101 | args[2] = xres; | ||
| 102 | args[3] = y2 - y1; | ||
| 103 | buf += y1 * xres; | ||
| 104 | auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args, | ||
| 105 | ((y2 - y1) * xres)/2, (u16 *) buf); | ||
| 106 | auok190x_send_command(par, AUOK190X_CMD_DATA_STOP); | ||
| 107 | |||
| 108 | par->update_cnt++; | ||
| 109 | |||
| 110 | mutex_unlock(&(par->io_lock)); | ||
| 111 | |||
| 112 | pm_runtime_mark_last_busy(dev); | ||
| 113 | pm_runtime_put_autosuspend(dev); | ||
| 114 | } | ||
| 115 | |||
| 116 | static void auok1900fb_dpy_update_pages(struct auok190xfb_par *par, | ||
| 117 | u16 y1, u16 y2) | ||
| 118 | { | ||
| 119 | int mode; | ||
| 120 | |||
| 121 | if (par->update_mode < 0) { | ||
| 122 | mode = AUOK190X_UPDATE_MODE(1); | ||
| 123 | par->last_mode = -1; | ||
| 124 | } else { | ||
| 125 | mode = AUOK190X_UPDATE_MODE(par->update_mode); | ||
| 126 | par->last_mode = par->update_mode; | ||
| 127 | } | ||
| 128 | |||
| 129 | if (par->flash) | ||
| 130 | mode |= AUOK190X_UPDATE_NONFLASH; | ||
| 131 | |||
| 132 | auok1900_update_region(par, mode, y1, y2); | ||
| 133 | } | ||
| 134 | |||
| 135 | static void auok1900fb_dpy_update(struct auok190xfb_par *par) | ||
| 136 | { | ||
| 137 | int mode; | ||
| 138 | |||
| 139 | if (par->update_mode < 0) { | ||
| 140 | mode = AUOK190X_UPDATE_MODE(0); | ||
| 141 | par->last_mode = -1; | ||
| 142 | } else { | ||
| 143 | mode = AUOK190X_UPDATE_MODE(par->update_mode); | ||
| 144 | par->last_mode = par->update_mode; | ||
| 145 | } | ||
| 146 | |||
| 147 | if (par->flash) | ||
| 148 | mode |= AUOK190X_UPDATE_NONFLASH; | ||
| 149 | |||
| 150 | auok1900_update_region(par, mode, 0, par->info->var.yres); | ||
| 151 | par->update_cnt = 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static bool auok1900fb_need_refresh(struct auok190xfb_par *par) | ||
| 155 | { | ||
| 156 | return (par->update_cnt > 10); | ||
| 157 | } | ||
| 158 | |||
| 159 | static int __devinit auok1900fb_probe(struct platform_device *pdev) | ||
| 160 | { | ||
| 161 | struct auok190x_init_data init; | ||
| 162 | struct auok190x_board *board; | ||
| 163 | |||
| 164 | /* pick up board specific routines */ | ||
| 165 | board = pdev->dev.platform_data; | ||
| 166 | if (!board) | ||
| 167 | return -EINVAL; | ||
| 168 | |||
| 169 | /* fill temporary init struct for common init */ | ||
| 170 | init.id = "auo_k1900fb"; | ||
| 171 | init.board = board; | ||
| 172 | init.update_partial = auok1900fb_dpy_update_pages; | ||
| 173 | init.update_all = auok1900fb_dpy_update; | ||
| 174 | init.need_refresh = auok1900fb_need_refresh; | ||
| 175 | init.init = auok1900_init; | ||
| 176 | |||
| 177 | return auok190x_common_probe(pdev, &init); | ||
| 178 | } | ||
| 179 | |||
| 180 | static int __devexit auok1900fb_remove(struct platform_device *pdev) | ||
| 181 | { | ||
| 182 | return auok190x_common_remove(pdev); | ||
| 183 | } | ||
| 184 | |||
| 185 | static struct platform_driver auok1900fb_driver = { | ||
| 186 | .probe = auok1900fb_probe, | ||
| 187 | .remove = __devexit_p(auok1900fb_remove), | ||
| 188 | .driver = { | ||
| 189 | .owner = THIS_MODULE, | ||
| 190 | .name = "auo_k1900fb", | ||
| 191 | .pm = &auok190x_pm, | ||
| 192 | }, | ||
| 193 | }; | ||
| 194 | module_platform_driver(auok1900fb_driver); | ||
| 195 | |||
| 196 | MODULE_DESCRIPTION("framebuffer driver for the AUO-K1900 EPD controller"); | ||
| 197 | MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); | ||
| 198 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/auo_k1901fb.c b/drivers/video/auo_k1901fb.c new file mode 100644 index 000000000000..1c054c18616e --- /dev/null +++ b/drivers/video/auo_k1901fb.c | |||
| @@ -0,0 +1,251 @@ | |||
| 1 | /* | ||
| 2 | * auok190xfb.c -- FB driver for AUO-K1901 controllers | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011, 2012 Heiko Stuebner <heiko@sntech.de> | ||
| 5 | * | ||
| 6 | * based on broadsheetfb.c | ||
| 7 | * | ||
| 8 | * Copyright (C) 2008, Jaya Kumar | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. | ||
| 15 | * | ||
| 16 | * This driver is written to be used with the AUO-K1901 display controller. | ||
| 17 | * | ||
| 18 | * It is intended to be architecture independent. A board specific driver | ||
| 19 | * must be used to perform all the physical IO interactions. | ||
| 20 | * | ||
| 21 | * The controller supports different update modes: | ||
| 22 | * mode0+1 16 step gray (4bit) | ||
| 23 | * mode2+3 4 step gray (2bit) | ||
| 24 | * mode4+5 2 step gray (1bit) | ||
| 25 | * - mode4 is described as "without LUT" | ||
| 26 | * mode7 automatic selection of update mode | ||
| 27 | * | ||
| 28 | * The most interesting difference to the K1900 is the ability to do screen | ||
| 29 | * updates in an asynchronous fashion. Where the K1900 needs to wait for the | ||
| 30 | * current update to complete, the K1901 can process later updates already. | ||
| 31 | */ | ||
| 32 | |||
| 33 | #include <linux/module.h> | ||
| 34 | #include <linux/kernel.h> | ||
| 35 | #include <linux/errno.h> | ||
| 36 | #include <linux/string.h> | ||
| 37 | #include <linux/mm.h> | ||
| 38 | #include <linux/slab.h> | ||
| 39 | #include <linux/delay.h> | ||
| 40 | #include <linux/interrupt.h> | ||
| 41 | #include <linux/fb.h> | ||
| 42 | #include <linux/init.h> | ||
| 43 | #include <linux/platform_device.h> | ||
| 44 | #include <linux/list.h> | ||
| 45 | #include <linux/firmware.h> | ||
| 46 | #include <linux/gpio.h> | ||
| 47 | #include <linux/pm_runtime.h> | ||
| 48 | |||
| 49 | #include <video/auo_k190xfb.h> | ||
| 50 | |||
| 51 | #include "auo_k190x.h" | ||
| 52 | |||
| 53 | /* | ||
| 54 | * AUO-K1901 specific commands | ||
| 55 | */ | ||
| 56 | |||
| 57 | #define AUOK1901_CMD_LUT_INTERFACE 0x0005 | ||
| 58 | #define AUOK1901_CMD_DMA_START 0x1001 | ||
| 59 | #define AUOK1901_CMD_CURSOR_START 0x1007 | ||
| 60 | #define AUOK1901_CMD_CURSOR_STOP AUOK190X_CMD_DATA_STOP | ||
| 61 | #define AUOK1901_CMD_DDMA_START 0x1009 | ||
| 62 | |||
| 63 | #define AUOK1901_INIT_GATE_PULSE_LOW (0 << 14) | ||
| 64 | #define AUOK1901_INIT_GATE_PULSE_HIGH (1 << 14) | ||
| 65 | #define AUOK1901_INIT_SINGLE_GATE (0 << 13) | ||
| 66 | #define AUOK1901_INIT_DOUBLE_GATE (1 << 13) | ||
| 67 | |||
| 68 | /* Bits to pixels | ||
| 69 | * Mode 15-12 11-8 7-4 3-0 | ||
| 70 | * format2 2 T 1 T | ||
| 71 | * format3 1 T 2 T | ||
| 72 | * format4 T 2 T 1 | ||
| 73 | * format5 T 1 T 2 | ||
| 74 | * | ||
| 75 | * halftone modes: | ||
| 76 | * format6 2 2 1 1 | ||
| 77 | * format7 1 1 2 2 | ||
| 78 | */ | ||
| 79 | #define AUOK1901_INIT_FORMAT2 (1 << 7) | ||
| 80 | #define AUOK1901_INIT_FORMAT3 ((1 << 7) | (1 << 6)) | ||
| 81 | #define AUOK1901_INIT_FORMAT4 (1 << 8) | ||
| 82 | #define AUOK1901_INIT_FORMAT5 ((1 << 8) | (1 << 6)) | ||
| 83 | #define AUOK1901_INIT_FORMAT6 ((1 << 8) | (1 << 7)) | ||
| 84 | #define AUOK1901_INIT_FORMAT7 ((1 << 8) | (1 << 7) | (1 << 6)) | ||
| 85 | |||
| 86 | /* res[4] to bit 10 | ||
| 87 | * res[3-0] to bits 5-2 | ||
| 88 | */ | ||
| 89 | #define AUOK1901_INIT_RESOLUTION(_res) (((_res & (1 << 4)) << 6) \ | ||
| 90 | | ((_res & 0xf) << 2)) | ||
| 91 | |||
| 92 | /* | ||
| 93 | * portrait / landscape orientation in AUOK1901_CMD_DMA_START | ||
| 94 | */ | ||
| 95 | #define AUOK1901_DMA_ROTATE90(_rot) ((_rot & 1) << 13) | ||
| 96 | |||
| 97 | /* | ||
| 98 | * equivalent to 1 << 11, needs the ~ to have same rotation like K1900 | ||
| 99 | */ | ||
| 100 | #define AUOK1901_DDMA_ROTATE180(_rot) ((~_rot & 2) << 10) | ||
| 101 | |||
| 102 | static void auok1901_init(struct auok190xfb_par *par) | ||
| 103 | { | ||
| 104 | struct auok190x_board *board = par->board; | ||
| 105 | u16 init_param = 0; | ||
| 106 | |||
| 107 | init_param |= AUOK190X_INIT_INVERSE_WHITE; | ||
| 108 | init_param |= AUOK190X_INIT_FORMAT0; | ||
| 109 | init_param |= AUOK1901_INIT_RESOLUTION(par->resolution); | ||
| 110 | init_param |= AUOK190X_INIT_SHIFT_LEFT; | ||
| 111 | |||
| 112 | auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param); | ||
| 113 | |||
| 114 | /* let the controller finish */ | ||
| 115 | board->wait_for_rdy(par); | ||
| 116 | } | ||
| 117 | |||
| 118 | static void auok1901_update_region(struct auok190xfb_par *par, int mode, | ||
| 119 | u16 y1, u16 y2) | ||
| 120 | { | ||
| 121 | struct device *dev = par->info->device; | ||
| 122 | unsigned char *buf = (unsigned char *)par->info->screen_base; | ||
| 123 | int xres = par->info->var.xres; | ||
| 124 | u16 args[5]; | ||
| 125 | |||
| 126 | pm_runtime_get_sync(dev); | ||
| 127 | |||
| 128 | mutex_lock(&(par->io_lock)); | ||
| 129 | |||
| 130 | /* y1 and y2 must be a multiple of 2 so drop the lowest bit */ | ||
| 131 | y1 &= 0xfffe; | ||
| 132 | y2 &= 0xfffe; | ||
| 133 | |||
| 134 | dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n", | ||
| 135 | 1, y1+1, xres, y2-y1, mode); | ||
| 136 | |||
| 137 | /* K1901: first transfer the region data */ | ||
| 138 | args[0] = AUOK1901_DMA_ROTATE90(par->rotation) | 1; | ||
| 139 | args[1] = y1 + 1; | ||
| 140 | args[2] = xres; | ||
| 141 | args[3] = y2 - y1; | ||
| 142 | buf += y1 * xres; | ||
| 143 | auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4, | ||
| 144 | args, ((y2 - y1) * xres)/2, | ||
| 145 | (u16 *) buf); | ||
| 146 | auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP); | ||
| 147 | |||
| 148 | /* K1901: second tell the controller to update the region with mode */ | ||
| 149 | args[0] = mode | AUOK1901_DDMA_ROTATE180(par->rotation); | ||
| 150 | args[1] = 1; | ||
| 151 | args[2] = y1 + 1; | ||
| 152 | args[3] = xres; | ||
| 153 | args[4] = y2 - y1; | ||
| 154 | auok190x_send_cmdargs_nowait(par, AUOK1901_CMD_DDMA_START, 5, args); | ||
| 155 | |||
| 156 | par->update_cnt++; | ||
| 157 | |||
| 158 | mutex_unlock(&(par->io_lock)); | ||
| 159 | |||
| 160 | pm_runtime_mark_last_busy(dev); | ||
| 161 | pm_runtime_put_autosuspend(dev); | ||
| 162 | } | ||
| 163 | |||
| 164 | static void auok1901fb_dpy_update_pages(struct auok190xfb_par *par, | ||
| 165 | u16 y1, u16 y2) | ||
| 166 | { | ||
| 167 | int mode; | ||
| 168 | |||
| 169 | if (par->update_mode < 0) { | ||
| 170 | mode = AUOK190X_UPDATE_MODE(1); | ||
| 171 | par->last_mode = -1; | ||
| 172 | } else { | ||
| 173 | mode = AUOK190X_UPDATE_MODE(par->update_mode); | ||
| 174 | par->last_mode = par->update_mode; | ||
| 175 | } | ||
| 176 | |||
| 177 | if (par->flash) | ||
| 178 | mode |= AUOK190X_UPDATE_NONFLASH; | ||
| 179 | |||
| 180 | auok1901_update_region(par, mode, y1, y2); | ||
| 181 | } | ||
| 182 | |||
| 183 | static void auok1901fb_dpy_update(struct auok190xfb_par *par) | ||
| 184 | { | ||
| 185 | int mode; | ||
| 186 | |||
| 187 | /* When doing full updates, wait for the controller to be ready | ||
| 188 | * This will hopefully catch some hangs of the K1901 | ||
| 189 | */ | ||
| 190 | par->board->wait_for_rdy(par); | ||
| 191 | |||
| 192 | if (par->update_mode < 0) { | ||
| 193 | mode = AUOK190X_UPDATE_MODE(0); | ||
| 194 | par->last_mode = -1; | ||
| 195 | } else { | ||
| 196 | mode = AUOK190X_UPDATE_MODE(par->update_mode); | ||
| 197 | par->last_mode = par->update_mode; | ||
| 198 | } | ||
| 199 | |||
| 200 | if (par->flash) | ||
| 201 | mode |= AUOK190X_UPDATE_NONFLASH; | ||
| 202 | |||
| 203 | auok1901_update_region(par, mode, 0, par->info->var.yres); | ||
| 204 | par->update_cnt = 0; | ||
| 205 | } | ||
| 206 | |||
| 207 | static bool auok1901fb_need_refresh(struct auok190xfb_par *par) | ||
| 208 | { | ||
| 209 | return (par->update_cnt > 10); | ||
| 210 | } | ||
| 211 | |||
| 212 | static int __devinit auok1901fb_probe(struct platform_device *pdev) | ||
| 213 | { | ||
| 214 | struct auok190x_init_data init; | ||
| 215 | struct auok190x_board *board; | ||
| 216 | |||
| 217 | /* pick up board specific routines */ | ||
| 218 | board = pdev->dev.platform_data; | ||
| 219 | if (!board) | ||
| 220 | return -EINVAL; | ||
| 221 | |||
| 222 | /* fill temporary init struct for common init */ | ||
| 223 | init.id = "auo_k1901fb"; | ||
| 224 | init.board = board; | ||
| 225 | init.update_partial = auok1901fb_dpy_update_pages; | ||
| 226 | init.update_all = auok1901fb_dpy_update; | ||
| 227 | init.need_refresh = auok1901fb_need_refresh; | ||
| 228 | init.init = auok1901_init; | ||
| 229 | |||
| 230 | return auok190x_common_probe(pdev, &init); | ||
| 231 | } | ||
| 232 | |||
| 233 | static int __devexit auok1901fb_remove(struct platform_device *pdev) | ||
| 234 | { | ||
| 235 | return auok190x_common_remove(pdev); | ||
| 236 | } | ||
| 237 | |||
| 238 | static struct platform_driver auok1901fb_driver = { | ||
| 239 | .probe = auok1901fb_probe, | ||
| 240 | .remove = __devexit_p(auok1901fb_remove), | ||
| 241 | .driver = { | ||
| 242 | .owner = THIS_MODULE, | ||
| 243 | .name = "auo_k1901fb", | ||
| 244 | .pm = &auok190x_pm, | ||
| 245 | }, | ||
| 246 | }; | ||
| 247 | module_platform_driver(auok1901fb_driver); | ||
| 248 | |||
| 249 | MODULE_DESCRIPTION("framebuffer driver for the AUO-K1901 EPD controller"); | ||
| 250 | MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); | ||
| 251 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/auo_k190x.c b/drivers/video/auo_k190x.c new file mode 100644 index 000000000000..77da6a2f43dc --- /dev/null +++ b/drivers/video/auo_k190x.c | |||
| @@ -0,0 +1,1046 @@ | |||
| 1 | /* | ||
| 2 | * Common code for AUO-K190X framebuffer drivers | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/gpio.h> | ||
| 14 | #include <linux/pm_runtime.h> | ||
| 15 | #include <linux/fb.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/uaccess.h> | ||
| 18 | #include <linux/vmalloc.h> | ||
| 19 | #include <linux/regulator/consumer.h> | ||
| 20 | |||
| 21 | #include <video/auo_k190xfb.h> | ||
| 22 | |||
| 23 | #include "auo_k190x.h" | ||
| 24 | |||
| 25 | struct panel_info { | ||
| 26 | int w; | ||
| 27 | int h; | ||
| 28 | }; | ||
| 29 | |||
| 30 | /* table of panel specific parameters to be indexed into by the board drivers */ | ||
| 31 | static struct panel_info panel_table[] = { | ||
| 32 | /* standard 6" */ | ||
| 33 | [AUOK190X_RESOLUTION_800_600] = { | ||
| 34 | .w = 800, | ||
| 35 | .h = 600, | ||
| 36 | }, | ||
| 37 | /* standard 9" */ | ||
| 38 | [AUOK190X_RESOLUTION_1024_768] = { | ||
| 39 | .w = 1024, | ||
| 40 | .h = 768, | ||
| 41 | }, | ||
| 42 | }; | ||
| 43 | |||
| 44 | /* | ||
| 45 | * private I80 interface to the board driver | ||
| 46 | */ | ||
| 47 | |||
| 48 | static void auok190x_issue_data(struct auok190xfb_par *par, u16 data) | ||
| 49 | { | ||
| 50 | par->board->set_ctl(par, AUOK190X_I80_WR, 0); | ||
| 51 | par->board->set_hdb(par, data); | ||
| 52 | par->board->set_ctl(par, AUOK190X_I80_WR, 1); | ||
| 53 | } | ||
| 54 | |||
| 55 | static void auok190x_issue_cmd(struct auok190xfb_par *par, u16 data) | ||
| 56 | { | ||
| 57 | par->board->set_ctl(par, AUOK190X_I80_DC, 0); | ||
| 58 | auok190x_issue_data(par, data); | ||
| 59 | par->board->set_ctl(par, AUOK190X_I80_DC, 1); | ||
| 60 | } | ||
| 61 | |||
| 62 | static int auok190x_issue_pixels(struct auok190xfb_par *par, int size, | ||
| 63 | u16 *data) | ||
| 64 | { | ||
| 65 | struct device *dev = par->info->device; | ||
| 66 | int i; | ||
| 67 | u16 tmp; | ||
| 68 | |||
| 69 | if (size & 3) { | ||
| 70 | dev_err(dev, "issue_pixels: size %d must be a multiple of 4\n", | ||
| 71 | size); | ||
| 72 | return -EINVAL; | ||
| 73 | } | ||
| 74 | |||
| 75 | for (i = 0; i < (size >> 1); i++) { | ||
| 76 | par->board->set_ctl(par, AUOK190X_I80_WR, 0); | ||
| 77 | |||
| 78 | /* simple reduction of 8bit staticgray to 4bit gray | ||
| 79 | * combines 4 * 4bit pixel values into a 16bit value | ||
| 80 | */ | ||
| 81 | tmp = (data[2*i] & 0xF0) >> 4; | ||
| 82 | tmp |= (data[2*i] & 0xF000) >> 8; | ||
| 83 | tmp |= (data[2*i+1] & 0xF0) << 4; | ||
| 84 | tmp |= (data[2*i+1] & 0xF000); | ||
| 85 | |||
| 86 | par->board->set_hdb(par, tmp); | ||
| 87 | par->board->set_ctl(par, AUOK190X_I80_WR, 1); | ||
| 88 | } | ||
| 89 | |||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | static u16 auok190x_read_data(struct auok190xfb_par *par) | ||
| 94 | { | ||
| 95 | u16 data; | ||
| 96 | |||
| 97 | par->board->set_ctl(par, AUOK190X_I80_OE, 0); | ||
| 98 | data = par->board->get_hdb(par); | ||
| 99 | par->board->set_ctl(par, AUOK190X_I80_OE, 1); | ||
| 100 | |||
| 101 | return data; | ||
| 102 | } | ||
| 103 | |||
| 104 | /* | ||
| 105 | * Command interface for the controller drivers | ||
| 106 | */ | ||
| 107 | |||
| 108 | void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data) | ||
| 109 | { | ||
| 110 | par->board->set_ctl(par, AUOK190X_I80_CS, 0); | ||
| 111 | auok190x_issue_cmd(par, data); | ||
| 112 | par->board->set_ctl(par, AUOK190X_I80_CS, 1); | ||
| 113 | } | ||
| 114 | EXPORT_SYMBOL_GPL(auok190x_send_command_nowait); | ||
| 115 | |||
| 116 | void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd, | ||
| 117 | int argc, u16 *argv) | ||
| 118 | { | ||
| 119 | int i; | ||
| 120 | |||
| 121 | par->board->set_ctl(par, AUOK190X_I80_CS, 0); | ||
| 122 | auok190x_issue_cmd(par, cmd); | ||
| 123 | |||
| 124 | for (i = 0; i < argc; i++) | ||
| 125 | auok190x_issue_data(par, argv[i]); | ||
| 126 | par->board->set_ctl(par, AUOK190X_I80_CS, 1); | ||
| 127 | } | ||
| 128 | EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_nowait); | ||
| 129 | |||
| 130 | int auok190x_send_command(struct auok190xfb_par *par, u16 data) | ||
| 131 | { | ||
| 132 | int ret; | ||
| 133 | |||
| 134 | ret = par->board->wait_for_rdy(par); | ||
| 135 | if (ret) | ||
| 136 | return ret; | ||
| 137 | |||
| 138 | auok190x_send_command_nowait(par, data); | ||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | EXPORT_SYMBOL_GPL(auok190x_send_command); | ||
| 142 | |||
| 143 | int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd, | ||
| 144 | int argc, u16 *argv) | ||
| 145 | { | ||
| 146 | int ret; | ||
| 147 | |||
| 148 | ret = par->board->wait_for_rdy(par); | ||
| 149 | if (ret) | ||
| 150 | return ret; | ||
| 151 | |||
| 152 | auok190x_send_cmdargs_nowait(par, cmd, argc, argv); | ||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | EXPORT_SYMBOL_GPL(auok190x_send_cmdargs); | ||
| 156 | |||
| 157 | int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd, | ||
| 158 | int argc, u16 *argv) | ||
| 159 | { | ||
| 160 | int i, ret; | ||
| 161 | |||
| 162 | ret = par->board->wait_for_rdy(par); | ||
| 163 | if (ret) | ||
| 164 | return ret; | ||
| 165 | |||
| 166 | par->board->set_ctl(par, AUOK190X_I80_CS, 0); | ||
| 167 | auok190x_issue_cmd(par, cmd); | ||
| 168 | |||
| 169 | for (i = 0; i < argc; i++) | ||
| 170 | argv[i] = auok190x_read_data(par); | ||
| 171 | par->board->set_ctl(par, AUOK190X_I80_CS, 1); | ||
| 172 | |||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | EXPORT_SYMBOL_GPL(auok190x_read_cmdargs); | ||
| 176 | |||
| 177 | void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par, u16 cmd, | ||
| 178 | int argc, u16 *argv, int size, u16 *data) | ||
| 179 | { | ||
| 180 | int i; | ||
| 181 | |||
| 182 | par->board->set_ctl(par, AUOK190X_I80_CS, 0); | ||
| 183 | |||
| 184 | auok190x_issue_cmd(par, cmd); | ||
| 185 | |||
| 186 | for (i = 0; i < argc; i++) | ||
| 187 | auok190x_issue_data(par, argv[i]); | ||
| 188 | |||
| 189 | auok190x_issue_pixels(par, size, data); | ||
| 190 | |||
| 191 | par->board->set_ctl(par, AUOK190X_I80_CS, 1); | ||
| 192 | } | ||
| 193 | EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels_nowait); | ||
| 194 | |||
| 195 | int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd, | ||
| 196 | int argc, u16 *argv, int size, u16 *data) | ||
| 197 | { | ||
| 198 | int ret; | ||
| 199 | |||
| 200 | ret = par->board->wait_for_rdy(par); | ||
| 201 | if (ret) | ||
| 202 | return ret; | ||
| 203 | |||
| 204 | auok190x_send_cmdargs_pixels_nowait(par, cmd, argc, argv, size, data); | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels); | ||
| 209 | |||
| 210 | /* | ||
| 211 | * fbdefio callbacks - common on both controllers. | ||
| 212 | */ | ||
| 213 | |||
| 214 | static void auok190xfb_dpy_first_io(struct fb_info *info) | ||
| 215 | { | ||
| 216 | /* tell runtime-pm that we wish to use the device in a short time */ | ||
| 217 | pm_runtime_get(info->device); | ||
| 218 | } | ||
| 219 | |||
| 220 | /* this is called back from the deferred io workqueue */ | ||
| 221 | static void auok190xfb_dpy_deferred_io(struct fb_info *info, | ||
| 222 | struct list_head *pagelist) | ||
| 223 | { | ||
| 224 | struct fb_deferred_io *fbdefio = info->fbdefio; | ||
| 225 | struct auok190xfb_par *par = info->par; | ||
| 226 | u16 yres = info->var.yres; | ||
| 227 | u16 xres = info->var.xres; | ||
| 228 | u16 y1 = 0, h = 0; | ||
| 229 | int prev_index = -1; | ||
| 230 | struct page *cur; | ||
| 231 | int h_inc; | ||
| 232 | int threshold; | ||
| 233 | |||
| 234 | if (!list_empty(pagelist)) | ||
| 235 | /* the device resume should've been requested through first_io, | ||
| 236 | * if the resume did not finish until now, wait for it. | ||
| 237 | */ | ||
| 238 | pm_runtime_barrier(info->device); | ||
| 239 | else | ||
| 240 | /* We reached this via the fsync or some other way. | ||
| 241 | * In either case the first_io function did not run, | ||
| 242 | * so we runtime_resume the device here synchronously. | ||
| 243 | */ | ||
| 244 | pm_runtime_get_sync(info->device); | ||
| 245 | |||
| 246 | /* Do a full screen update every n updates to prevent | ||
| 247 | * excessive darkening of the Sipix display. | ||
| 248 | * If we do this, there is no need to walk the pages. | ||
| 249 | */ | ||
| 250 | if (par->need_refresh(par)) { | ||
| 251 | par->update_all(par); | ||
| 252 | goto out; | ||
| 253 | } | ||
| 254 | |||
| 255 | /* height increment is fixed per page */ | ||
| 256 | h_inc = DIV_ROUND_UP(PAGE_SIZE , xres); | ||
| 257 | |||
| 258 | /* calculate number of pages from pixel height */ | ||
| 259 | threshold = par->consecutive_threshold / h_inc; | ||
| 260 | if (threshold < 1) | ||
| 261 | threshold = 1; | ||
| 262 | |||
| 263 | /* walk the written page list and swizzle the data */ | ||
| 264 | list_for_each_entry(cur, &fbdefio->pagelist, lru) { | ||
| 265 | if (prev_index < 0) { | ||
| 266 | /* just starting so assign first page */ | ||
| 267 | y1 = (cur->index << PAGE_SHIFT) / xres; | ||
| 268 | h = h_inc; | ||
| 269 | } else if ((cur->index - prev_index) <= threshold) { | ||
| 270 | /* page is within our threshold for single updates */ | ||
| 271 | h += h_inc * (cur->index - prev_index); | ||
| 272 | } else { | ||
| 273 | /* page not consecutive, issue previous update first */ | ||
| 274 | par->update_partial(par, y1, y1 + h); | ||
| 275 | |||
| 276 | /* start over with our non consecutive page */ | ||
| 277 | y1 = (cur->index << PAGE_SHIFT) / xres; | ||
| 278 | h = h_inc; | ||
| 279 | } | ||
| 280 | prev_index = cur->index; | ||
| 281 | } | ||
| 282 | |||
| 283 | /* if we still have any pages to update we do so now */ | ||
| 284 | if (h >= yres) | ||
| 285 | /* its a full screen update, just do it */ | ||
| 286 | par->update_all(par); | ||
| 287 | else | ||
| 288 | par->update_partial(par, y1, min((u16) (y1 + h), yres)); | ||
| 289 | |||
| 290 | out: | ||
| 291 | pm_runtime_mark_last_busy(info->device); | ||
| 292 | pm_runtime_put_autosuspend(info->device); | ||
| 293 | } | ||
| 294 | |||
| 295 | /* | ||
| 296 | * framebuffer operations | ||
| 297 | */ | ||
| 298 | |||
| 299 | /* | ||
| 300 | * this is the slow path from userspace. they can seek and write to | ||
| 301 | * the fb. it's inefficient to do anything less than a full screen draw | ||
| 302 | */ | ||
| 303 | static ssize_t auok190xfb_write(struct fb_info *info, const char __user *buf, | ||
| 304 | size_t count, loff_t *ppos) | ||
| 305 | { | ||
| 306 | struct auok190xfb_par *par = info->par; | ||
| 307 | unsigned long p = *ppos; | ||
| 308 | void *dst; | ||
| 309 | int err = 0; | ||
| 310 | unsigned long total_size; | ||
| 311 | |||
| 312 | if (info->state != FBINFO_STATE_RUNNING) | ||
| 313 | return -EPERM; | ||
| 314 | |||
| 315 | total_size = info->fix.smem_len; | ||
| 316 | |||
| 317 | if (p > total_size) | ||
| 318 | return -EFBIG; | ||
| 319 | |||
| 320 | if (count > total_size) { | ||
| 321 | err = -EFBIG; | ||
| 322 | count = total_size; | ||
| 323 | } | ||
| 324 | |||
| 325 | if (count + p > total_size) { | ||
| 326 | if (!err) | ||
| 327 | err = -ENOSPC; | ||
| 328 | |||
| 329 | count = total_size - p; | ||
| 330 | } | ||
| 331 | |||
| 332 | dst = (void *)(info->screen_base + p); | ||
| 333 | |||
| 334 | if (copy_from_user(dst, buf, count)) | ||
| 335 | err = -EFAULT; | ||
| 336 | |||
| 337 | if (!err) | ||
| 338 | *ppos += count; | ||
| 339 | |||
| 340 | par->update_all(par); | ||
| 341 | |||
| 342 | return (err) ? err : count; | ||
| 343 | } | ||
| 344 | |||
| 345 | static void auok190xfb_fillrect(struct fb_info *info, | ||
| 346 | const struct fb_fillrect *rect) | ||
| 347 | { | ||
| 348 | struct auok190xfb_par *par = info->par; | ||
| 349 | |||
| 350 | sys_fillrect(info, rect); | ||
| 351 | |||
| 352 | par->update_all(par); | ||
| 353 | } | ||
| 354 | |||
| 355 | static void auok190xfb_copyarea(struct fb_info *info, | ||
| 356 | const struct fb_copyarea *area) | ||
| 357 | { | ||
| 358 | struct auok190xfb_par *par = info->par; | ||
| 359 | |||
| 360 | sys_copyarea(info, area); | ||
| 361 | |||
| 362 | par->update_all(par); | ||
| 363 | } | ||
| 364 | |||
| 365 | static void auok190xfb_imageblit(struct fb_info *info, | ||
| 366 | const struct fb_image *image) | ||
| 367 | { | ||
| 368 | struct auok190xfb_par *par = info->par; | ||
| 369 | |||
| 370 | sys_imageblit(info, image); | ||
| 371 | |||
| 372 | par->update_all(par); | ||
| 373 | } | ||
| 374 | |||
| 375 | static int auok190xfb_check_var(struct fb_var_screeninfo *var, | ||
| 376 | struct fb_info *info) | ||
| 377 | { | ||
| 378 | if (info->var.xres != var->xres || info->var.yres != var->yres || | ||
| 379 | info->var.xres_virtual != var->xres_virtual || | ||
| 380 | info->var.yres_virtual != var->yres_virtual) { | ||
| 381 | pr_info("%s: Resolution not supported: X%u x Y%u\n", | ||
| 382 | __func__, var->xres, var->yres); | ||
| 383 | return -EINVAL; | ||
| 384 | } | ||
| 385 | |||
| 386 | /* | ||
| 387 | * Memory limit | ||
| 388 | */ | ||
| 389 | |||
| 390 | if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) { | ||
| 391 | pr_info("%s: Memory Limit requested yres_virtual = %u\n", | ||
| 392 | __func__, var->yres_virtual); | ||
| 393 | return -ENOMEM; | ||
| 394 | } | ||
| 395 | |||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | static struct fb_ops auok190xfb_ops = { | ||
| 400 | .owner = THIS_MODULE, | ||
| 401 | .fb_read = fb_sys_read, | ||
| 402 | .fb_write = auok190xfb_write, | ||
| 403 | .fb_fillrect = auok190xfb_fillrect, | ||
| 404 | .fb_copyarea = auok190xfb_copyarea, | ||
| 405 | .fb_imageblit = auok190xfb_imageblit, | ||
| 406 | .fb_check_var = auok190xfb_check_var, | ||
| 407 | }; | ||
| 408 | |||
| 409 | /* | ||
| 410 | * Controller-functions common to both K1900 and K1901 | ||
| 411 | */ | ||
| 412 | |||
| 413 | static int auok190x_read_temperature(struct auok190xfb_par *par) | ||
| 414 | { | ||
| 415 | struct device *dev = par->info->device; | ||
| 416 | u16 data[4]; | ||
| 417 | int temp; | ||
| 418 | |||
| 419 | pm_runtime_get_sync(dev); | ||
| 420 | |||
| 421 | mutex_lock(&(par->io_lock)); | ||
| 422 | |||
| 423 | auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data); | ||
| 424 | |||
| 425 | mutex_unlock(&(par->io_lock)); | ||
| 426 | |||
| 427 | pm_runtime_mark_last_busy(dev); | ||
| 428 | pm_runtime_put_autosuspend(dev); | ||
| 429 | |||
| 430 | /* sanitize and split of half-degrees for now */ | ||
| 431 | temp = ((data[0] & AUOK190X_VERSION_TEMP_MASK) >> 1); | ||
| 432 | |||
| 433 | /* handle positive and negative temperatures */ | ||
| 434 | if (temp >= 201) | ||
| 435 | return (255 - temp + 1) * (-1); | ||
| 436 | else | ||
| 437 | return temp; | ||
| 438 | } | ||
| 439 | |||
| 440 | static void auok190x_identify(struct auok190xfb_par *par) | ||
| 441 | { | ||
| 442 | struct device *dev = par->info->device; | ||
| 443 | u16 data[4]; | ||
| 444 | |||
| 445 | pm_runtime_get_sync(dev); | ||
| 446 | |||
| 447 | mutex_lock(&(par->io_lock)); | ||
| 448 | |||
| 449 | auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data); | ||
| 450 | |||
| 451 | mutex_unlock(&(par->io_lock)); | ||
| 452 | |||
| 453 | par->epd_type = data[1] & AUOK190X_VERSION_TEMP_MASK; | ||
| 454 | |||
| 455 | par->panel_size_int = AUOK190X_VERSION_SIZE_INT(data[2]); | ||
| 456 | par->panel_size_float = AUOK190X_VERSION_SIZE_FLOAT(data[2]); | ||
| 457 | par->panel_model = AUOK190X_VERSION_MODEL(data[2]); | ||
| 458 | |||
| 459 | par->tcon_version = AUOK190X_VERSION_TCON(data[3]); | ||
| 460 | par->lut_version = AUOK190X_VERSION_LUT(data[3]); | ||
| 461 | |||
| 462 | dev_dbg(dev, "panel %d.%din, model 0x%x, EPD 0x%x TCON-rev 0x%x, LUT-rev 0x%x", | ||
| 463 | par->panel_size_int, par->panel_size_float, par->panel_model, | ||
| 464 | par->epd_type, par->tcon_version, par->lut_version); | ||
| 465 | |||
| 466 | pm_runtime_mark_last_busy(dev); | ||
| 467 | pm_runtime_put_autosuspend(dev); | ||
| 468 | } | ||
| 469 | |||
| 470 | /* | ||
| 471 | * Sysfs functions | ||
| 472 | */ | ||
| 473 | |||
| 474 | static ssize_t update_mode_show(struct device *dev, | ||
| 475 | struct device_attribute *attr, char *buf) | ||
| 476 | { | ||
| 477 | struct fb_info *info = dev_get_drvdata(dev); | ||
| 478 | struct auok190xfb_par *par = info->par; | ||
| 479 | |||
| 480 | return sprintf(buf, "%d\n", par->update_mode); | ||
| 481 | } | ||
| 482 | |||
| 483 | static ssize_t update_mode_store(struct device *dev, | ||
| 484 | struct device_attribute *attr, | ||
| 485 | const char *buf, size_t count) | ||
| 486 | { | ||
| 487 | struct fb_info *info = dev_get_drvdata(dev); | ||
| 488 | struct auok190xfb_par *par = info->par; | ||
| 489 | int mode, ret; | ||
| 490 | |||
| 491 | ret = kstrtoint(buf, 10, &mode); | ||
| 492 | if (ret) | ||
| 493 | return ret; | ||
| 494 | |||
| 495 | par->update_mode = mode; | ||
| 496 | |||
| 497 | /* if we enter a better mode, do a full update */ | ||
| 498 | if (par->last_mode > 1 && mode < par->last_mode) | ||
| 499 | par->update_all(par); | ||
| 500 | |||
| 501 | return count; | ||
| 502 | } | ||
| 503 | |||
| 504 | static ssize_t flash_show(struct device *dev, struct device_attribute *attr, | ||
| 505 | char *buf) | ||
| 506 | { | ||
| 507 | struct fb_info *info = dev_get_drvdata(dev); | ||
| 508 | struct auok190xfb_par *par = info->par; | ||
| 509 | |||
| 510 | return sprintf(buf, "%d\n", par->flash); | ||
| 511 | } | ||
| 512 | |||
| 513 | static ssize_t flash_store(struct device *dev, struct device_attribute *attr, | ||
| 514 | const char *buf, size_t count) | ||
| 515 | { | ||
| 516 | struct fb_info *info = dev_get_drvdata(dev); | ||
| 517 | struct auok190xfb_par *par = info->par; | ||
| 518 | int flash, ret; | ||
| 519 | |||
| 520 | ret = kstrtoint(buf, 10, &flash); | ||
| 521 | if (ret) | ||
| 522 | return ret; | ||
| 523 | |||
| 524 | if (flash > 0) | ||
| 525 | par->flash = 1; | ||
| 526 | else | ||
| 527 | par->flash = 0; | ||
| 528 | |||
| 529 | return count; | ||
| 530 | } | ||
| 531 | |||
| 532 | static ssize_t temp_show(struct device *dev, struct device_attribute *attr, | ||
| 533 | char *buf) | ||
| 534 | { | ||
| 535 | struct fb_info *info = dev_get_drvdata(dev); | ||
| 536 | struct auok190xfb_par *par = info->par; | ||
| 537 | int temp; | ||
| 538 | |||
| 539 | temp = auok190x_read_temperature(par); | ||
| 540 | return sprintf(buf, "%d\n", temp); | ||
| 541 | } | ||
| 542 | |||
| 543 | static DEVICE_ATTR(update_mode, 0644, update_mode_show, update_mode_store); | ||
| 544 | static DEVICE_ATTR(flash, 0644, flash_show, flash_store); | ||
| 545 | static DEVICE_ATTR(temp, 0644, temp_show, NULL); | ||
| 546 | |||
| 547 | static struct attribute *auok190x_attributes[] = { | ||
| 548 | &dev_attr_update_mode.attr, | ||
| 549 | &dev_attr_flash.attr, | ||
| 550 | &dev_attr_temp.attr, | ||
| 551 | NULL | ||
| 552 | }; | ||
| 553 | |||
| 554 | static const struct attribute_group auok190x_attr_group = { | ||
| 555 | .attrs = auok190x_attributes, | ||
| 556 | }; | ||
| 557 | |||
| 558 | static int auok190x_power(struct auok190xfb_par *par, bool on) | ||
| 559 | { | ||
| 560 | struct auok190x_board *board = par->board; | ||
| 561 | int ret; | ||
| 562 | |||
| 563 | if (on) { | ||
| 564 | /* We should maintain POWER up for at least 80ms before set | ||
| 565 | * RST_N and SLP_N to high (TCON spec 20100803_v35 p59) | ||
| 566 | */ | ||
| 567 | ret = regulator_enable(par->regulator); | ||
| 568 | if (ret) | ||
| 569 | return ret; | ||
| 570 | |||
| 571 | msleep(200); | ||
| 572 | gpio_set_value(board->gpio_nrst, 1); | ||
| 573 | gpio_set_value(board->gpio_nsleep, 1); | ||
| 574 | msleep(200); | ||
| 575 | } else { | ||
| 576 | regulator_disable(par->regulator); | ||
| 577 | gpio_set_value(board->gpio_nrst, 0); | ||
| 578 | gpio_set_value(board->gpio_nsleep, 0); | ||
| 579 | } | ||
| 580 | |||
| 581 | return 0; | ||
| 582 | } | ||
| 583 | |||
| 584 | /* | ||
| 585 | * Recovery - powercycle the controller | ||
| 586 | */ | ||
| 587 | |||
| 588 | static void auok190x_recover(struct auok190xfb_par *par) | ||
| 589 | { | ||
| 590 | auok190x_power(par, 0); | ||
| 591 | msleep(100); | ||
| 592 | auok190x_power(par, 1); | ||
| 593 | |||
| 594 | par->init(par); | ||
| 595 | |||
| 596 | /* wait for init to complete */ | ||
| 597 | par->board->wait_for_rdy(par); | ||
| 598 | } | ||
| 599 | |||
| 600 | /* | ||
| 601 | * Power-management | ||
| 602 | */ | ||
| 603 | |||
| 604 | #ifdef CONFIG_PM | ||
| 605 | static int auok190x_runtime_suspend(struct device *dev) | ||
| 606 | { | ||
| 607 | struct platform_device *pdev = to_platform_device(dev); | ||
| 608 | struct fb_info *info = platform_get_drvdata(pdev); | ||
| 609 | struct auok190xfb_par *par = info->par; | ||
| 610 | struct auok190x_board *board = par->board; | ||
| 611 | u16 standby_param; | ||
| 612 | |||
| 613 | /* take and keep the lock until we are resumed, as the controller | ||
| 614 | * will never reach the non-busy state when in standby mode | ||
| 615 | */ | ||
| 616 | mutex_lock(&(par->io_lock)); | ||
| 617 | |||
| 618 | if (par->standby) { | ||
| 619 | dev_warn(dev, "already in standby, runtime-pm pairing mismatch\n"); | ||
| 620 | mutex_unlock(&(par->io_lock)); | ||
| 621 | return 0; | ||
| 622 | } | ||
| 623 | |||
| 624 | /* according to runtime_pm.txt runtime_suspend only means, that the | ||
| 625 | * device will not process data and will not communicate with the CPU | ||
| 626 | * As we hold the lock, this stays true even without standby | ||
| 627 | */ | ||
| 628 | if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) { | ||
| 629 | dev_dbg(dev, "runtime suspend without standby\n"); | ||
| 630 | goto finish; | ||
| 631 | } else if (board->quirks & AUOK190X_QUIRK_STANDBYPARAM) { | ||
| 632 | /* for some TCON versions STANDBY expects a parameter (0) but | ||
| 633 | * it seems the real tcon version has to be determined yet. | ||
| 634 | */ | ||
| 635 | dev_dbg(dev, "runtime suspend with additional empty param\n"); | ||
| 636 | standby_param = 0; | ||
| 637 | auok190x_send_cmdargs(par, AUOK190X_CMD_STANDBY, 1, | ||
| 638 | &standby_param); | ||
| 639 | } else { | ||
| 640 | dev_dbg(dev, "runtime suspend without param\n"); | ||
| 641 | auok190x_send_command(par, AUOK190X_CMD_STANDBY); | ||
| 642 | } | ||
| 643 | |||
| 644 | msleep(64); | ||
| 645 | |||
| 646 | finish: | ||
| 647 | par->standby = 1; | ||
| 648 | |||
| 649 | return 0; | ||
| 650 | } | ||
| 651 | |||
| 652 | static int auok190x_runtime_resume(struct device *dev) | ||
| 653 | { | ||
| 654 | struct platform_device *pdev = to_platform_device(dev); | ||
| 655 | struct fb_info *info = platform_get_drvdata(pdev); | ||
| 656 | struct auok190xfb_par *par = info->par; | ||
| 657 | struct auok190x_board *board = par->board; | ||
| 658 | |||
| 659 | if (!par->standby) { | ||
| 660 | dev_warn(dev, "not in standby, runtime-pm pairing mismatch\n"); | ||
| 661 | return 0; | ||
| 662 | } | ||
| 663 | |||
| 664 | if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) { | ||
| 665 | dev_dbg(dev, "runtime resume without standby\n"); | ||
| 666 | } else { | ||
| 667 | /* when in standby, controller is always busy | ||
| 668 | * and only accepts the wakeup command | ||
| 669 | */ | ||
| 670 | dev_dbg(dev, "runtime resume from standby\n"); | ||
| 671 | auok190x_send_command_nowait(par, AUOK190X_CMD_WAKEUP); | ||
| 672 | |||
| 673 | msleep(160); | ||
| 674 | |||
| 675 | /* wait for the controller to be ready and release the lock */ | ||
| 676 | board->wait_for_rdy(par); | ||
| 677 | } | ||
| 678 | |||
| 679 | par->standby = 0; | ||
| 680 | |||
| 681 | mutex_unlock(&(par->io_lock)); | ||
| 682 | |||
| 683 | return 0; | ||
| 684 | } | ||
| 685 | |||
| 686 | static int auok190x_suspend(struct device *dev) | ||
| 687 | { | ||
| 688 | struct platform_device *pdev = to_platform_device(dev); | ||
| 689 | struct fb_info *info = platform_get_drvdata(pdev); | ||
| 690 | struct auok190xfb_par *par = info->par; | ||
| 691 | struct auok190x_board *board = par->board; | ||
| 692 | int ret; | ||
| 693 | |||
| 694 | dev_dbg(dev, "suspend\n"); | ||
| 695 | if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) { | ||
| 696 | /* suspend via powering off the ic */ | ||
| 697 | dev_dbg(dev, "suspend with broken standby\n"); | ||
| 698 | |||
| 699 | auok190x_power(par, 0); | ||
| 700 | } else { | ||
| 701 | dev_dbg(dev, "suspend using sleep\n"); | ||
| 702 | |||
| 703 | /* the sleep state can only be entered from the standby state. | ||
| 704 | * pm_runtime_get_noresume gets called before the suspend call. | ||
| 705 | * So the devices usage count is >0 but it is not necessarily | ||
| 706 | * active. | ||
| 707 | */ | ||
| 708 | if (!pm_runtime_status_suspended(dev)) { | ||
| 709 | ret = auok190x_runtime_suspend(dev); | ||
| 710 | if (ret < 0) { | ||
| 711 | dev_err(dev, "auok190x_runtime_suspend failed with %d\n", | ||
| 712 | ret); | ||
| 713 | return ret; | ||
| 714 | } | ||
| 715 | par->manual_standby = 1; | ||
| 716 | } | ||
| 717 | |||
| 718 | gpio_direction_output(board->gpio_nsleep, 0); | ||
| 719 | } | ||
| 720 | |||
| 721 | msleep(100); | ||
| 722 | |||
| 723 | return 0; | ||
| 724 | } | ||
| 725 | |||
| 726 | static int auok190x_resume(struct device *dev) | ||
| 727 | { | ||
| 728 | struct platform_device *pdev = to_platform_device(dev); | ||
| 729 | struct fb_info *info = platform_get_drvdata(pdev); | ||
| 730 | struct auok190xfb_par *par = info->par; | ||
| 731 | struct auok190x_board *board = par->board; | ||
| 732 | |||
| 733 | dev_dbg(dev, "resume\n"); | ||
| 734 | if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) { | ||
| 735 | dev_dbg(dev, "resume with broken standby\n"); | ||
| 736 | |||
| 737 | auok190x_power(par, 1); | ||
| 738 | |||
| 739 | par->init(par); | ||
| 740 | } else { | ||
| 741 | dev_dbg(dev, "resume from sleep\n"); | ||
| 742 | |||
| 743 | /* device should be in runtime suspend when we were suspended | ||
| 744 | * and pm_runtime_put_sync gets called after this function. | ||
| 745 | * So there is no need to touch the standby mode here at all. | ||
| 746 | */ | ||
| 747 | gpio_direction_output(board->gpio_nsleep, 1); | ||
| 748 | msleep(100); | ||
| 749 | |||
| 750 | /* an additional init call seems to be necessary after sleep */ | ||
| 751 | auok190x_runtime_resume(dev); | ||
| 752 | par->init(par); | ||
| 753 | |||
| 754 | /* if we were runtime-suspended before, suspend again*/ | ||
| 755 | if (!par->manual_standby) | ||
| 756 | auok190x_runtime_suspend(dev); | ||
| 757 | else | ||
| 758 | par->manual_standby = 0; | ||
| 759 | } | ||
| 760 | |||
| 761 | return 0; | ||
| 762 | } | ||
| 763 | #endif | ||
| 764 | |||
| 765 | const struct dev_pm_ops auok190x_pm = { | ||
| 766 | SET_RUNTIME_PM_OPS(auok190x_runtime_suspend, auok190x_runtime_resume, | ||
| 767 | NULL) | ||
| 768 | SET_SYSTEM_SLEEP_PM_OPS(auok190x_suspend, auok190x_resume) | ||
| 769 | }; | ||
| 770 | EXPORT_SYMBOL_GPL(auok190x_pm); | ||
| 771 | |||
| 772 | /* | ||
| 773 | * Common probe and remove code | ||
| 774 | */ | ||
| 775 | |||
| 776 | int __devinit auok190x_common_probe(struct platform_device *pdev, | ||
| 777 | struct auok190x_init_data *init) | ||
| 778 | { | ||
| 779 | struct auok190x_board *board = init->board; | ||
| 780 | struct auok190xfb_par *par; | ||
| 781 | struct fb_info *info; | ||
| 782 | struct panel_info *panel; | ||
| 783 | int videomemorysize, ret; | ||
| 784 | unsigned char *videomemory; | ||
| 785 | |||
| 786 | /* check board contents */ | ||
| 787 | if (!board->init || !board->cleanup || !board->wait_for_rdy | ||
| 788 | || !board->set_ctl || !board->set_hdb || !board->get_hdb | ||
| 789 | || !board->setup_irq) | ||
| 790 | return -EINVAL; | ||
| 791 | |||
| 792 | info = framebuffer_alloc(sizeof(struct auok190xfb_par), &pdev->dev); | ||
| 793 | if (!info) | ||
| 794 | return -ENOMEM; | ||
| 795 | |||
| 796 | par = info->par; | ||
| 797 | par->info = info; | ||
| 798 | par->board = board; | ||
| 799 | par->recover = auok190x_recover; | ||
| 800 | par->update_partial = init->update_partial; | ||
| 801 | par->update_all = init->update_all; | ||
| 802 | par->need_refresh = init->need_refresh; | ||
| 803 | par->init = init->init; | ||
| 804 | |||
| 805 | /* init update modes */ | ||
| 806 | par->update_cnt = 0; | ||
| 807 | par->update_mode = -1; | ||
| 808 | par->last_mode = -1; | ||
| 809 | par->flash = 0; | ||
| 810 | |||
| 811 | par->regulator = regulator_get(info->device, "vdd"); | ||
| 812 | if (IS_ERR(par->regulator)) { | ||
| 813 | ret = PTR_ERR(par->regulator); | ||
| 814 | dev_err(info->device, "Failed to get regulator: %d\n", ret); | ||
| 815 | goto err_reg; | ||
| 816 | } | ||
| 817 | |||
| 818 | ret = board->init(par); | ||
| 819 | if (ret) { | ||
| 820 | dev_err(info->device, "board init failed, %d\n", ret); | ||
| 821 | goto err_board; | ||
| 822 | } | ||
| 823 | |||
| 824 | ret = gpio_request(board->gpio_nsleep, "AUOK190x sleep"); | ||
| 825 | if (ret) { | ||
| 826 | dev_err(info->device, "could not request sleep gpio, %d\n", | ||
| 827 | ret); | ||
| 828 | goto err_gpio1; | ||
| 829 | } | ||
| 830 | |||
| 831 | ret = gpio_direction_output(board->gpio_nsleep, 0); | ||
| 832 | if (ret) { | ||
| 833 | dev_err(info->device, "could not set sleep gpio, %d\n", ret); | ||
| 834 | goto err_gpio2; | ||
| 835 | } | ||
| 836 | |||
| 837 | ret = gpio_request(board->gpio_nrst, "AUOK190x reset"); | ||
| 838 | if (ret) { | ||
| 839 | dev_err(info->device, "could not request reset gpio, %d\n", | ||
| 840 | ret); | ||
| 841 | goto err_gpio2; | ||
| 842 | } | ||
| 843 | |||
| 844 | ret = gpio_direction_output(board->gpio_nrst, 0); | ||
| 845 | if (ret) { | ||
| 846 | dev_err(info->device, "could not set reset gpio, %d\n", ret); | ||
| 847 | goto err_gpio3; | ||
| 848 | } | ||
| 849 | |||
| 850 | ret = auok190x_power(par, 1); | ||
| 851 | if (ret) { | ||
| 852 | dev_err(info->device, "could not power on the device, %d\n", | ||
| 853 | ret); | ||
| 854 | goto err_gpio3; | ||
| 855 | } | ||
| 856 | |||
| 857 | mutex_init(&par->io_lock); | ||
| 858 | |||
| 859 | init_waitqueue_head(&par->waitq); | ||
| 860 | |||
| 861 | ret = par->board->setup_irq(par->info); | ||
| 862 | if (ret) { | ||
| 863 | dev_err(info->device, "could not setup ready-irq, %d\n", ret); | ||
| 864 | goto err_irq; | ||
| 865 | } | ||
| 866 | |||
| 867 | /* wait for init to complete */ | ||
| 868 | par->board->wait_for_rdy(par); | ||
| 869 | |||
| 870 | /* | ||
| 871 | * From here on the controller can talk to us | ||
| 872 | */ | ||
| 873 | |||
| 874 | /* initialise fix, var, resolution and rotation */ | ||
| 875 | |||
| 876 | strlcpy(info->fix.id, init->id, 16); | ||
| 877 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
| 878 | info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; | ||
| 879 | info->fix.xpanstep = 0; | ||
| 880 | info->fix.ypanstep = 0; | ||
| 881 | info->fix.ywrapstep = 0; | ||
| 882 | info->fix.accel = FB_ACCEL_NONE; | ||
| 883 | |||
| 884 | info->var.bits_per_pixel = 8; | ||
| 885 | info->var.grayscale = 1; | ||
| 886 | info->var.red.length = 8; | ||
| 887 | info->var.green.length = 8; | ||
| 888 | info->var.blue.length = 8; | ||
| 889 | |||
| 890 | panel = &panel_table[board->resolution]; | ||
| 891 | |||
| 892 | /* if 90 degree rotation, switch width and height */ | ||
| 893 | if (board->rotation & 1) { | ||
| 894 | info->var.xres = panel->h; | ||
| 895 | info->var.yres = panel->w; | ||
| 896 | info->var.xres_virtual = panel->h; | ||
| 897 | info->var.yres_virtual = panel->w; | ||
| 898 | info->fix.line_length = panel->h; | ||
| 899 | } else { | ||
| 900 | info->var.xres = panel->w; | ||
| 901 | info->var.yres = panel->h; | ||
| 902 | info->var.xres_virtual = panel->w; | ||
| 903 | info->var.yres_virtual = panel->h; | ||
| 904 | info->fix.line_length = panel->w; | ||
| 905 | } | ||
| 906 | |||
| 907 | par->resolution = board->resolution; | ||
| 908 | par->rotation = board->rotation; | ||
| 909 | |||
| 910 | /* videomemory handling */ | ||
| 911 | |||
| 912 | videomemorysize = roundup((panel->w * panel->h), PAGE_SIZE); | ||
| 913 | videomemory = vmalloc(videomemorysize); | ||
| 914 | if (!videomemory) { | ||
| 915 | ret = -ENOMEM; | ||
| 916 | goto err_irq; | ||
| 917 | } | ||
| 918 | |||
| 919 | memset(videomemory, 0, videomemorysize); | ||
| 920 | info->screen_base = (char *)videomemory; | ||
| 921 | info->fix.smem_len = videomemorysize; | ||
| 922 | |||
| 923 | info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; | ||
| 924 | info->fbops = &auok190xfb_ops; | ||
| 925 | |||
| 926 | /* deferred io init */ | ||
| 927 | |||
| 928 | info->fbdefio = devm_kzalloc(info->device, | ||
| 929 | sizeof(struct fb_deferred_io), | ||
| 930 | GFP_KERNEL); | ||
| 931 | if (!info->fbdefio) { | ||
| 932 | dev_err(info->device, "Failed to allocate memory\n"); | ||
| 933 | ret = -ENOMEM; | ||
| 934 | goto err_defio; | ||
| 935 | } | ||
| 936 | |||
| 937 | dev_dbg(info->device, "targetting %d frames per second\n", board->fps); | ||
| 938 | info->fbdefio->delay = HZ / board->fps; | ||
| 939 | info->fbdefio->first_io = auok190xfb_dpy_first_io, | ||
| 940 | info->fbdefio->deferred_io = auok190xfb_dpy_deferred_io, | ||
| 941 | fb_deferred_io_init(info); | ||
| 942 | |||
| 943 | /* color map */ | ||
| 944 | |||
| 945 | ret = fb_alloc_cmap(&info->cmap, 256, 0); | ||
| 946 | if (ret < 0) { | ||
| 947 | dev_err(info->device, "Failed to allocate colormap\n"); | ||
| 948 | goto err_cmap; | ||
| 949 | } | ||
| 950 | |||
| 951 | /* controller init */ | ||
| 952 | |||
| 953 | par->consecutive_threshold = 100; | ||
| 954 | par->init(par); | ||
| 955 | auok190x_identify(par); | ||
| 956 | |||
| 957 | platform_set_drvdata(pdev, info); | ||
| 958 | |||
| 959 | ret = register_framebuffer(info); | ||
| 960 | if (ret < 0) | ||
| 961 | goto err_regfb; | ||
| 962 | |||
| 963 | ret = sysfs_create_group(&info->device->kobj, &auok190x_attr_group); | ||
| 964 | if (ret) | ||
| 965 | goto err_sysfs; | ||
| 966 | |||
| 967 | dev_info(info->device, "fb%d: %dx%d using %dK of video memory\n", | ||
| 968 | info->node, info->var.xres, info->var.yres, | ||
| 969 | videomemorysize >> 10); | ||
| 970 | |||
| 971 | /* increase autosuspend_delay when we use alternative methods | ||
| 972 | * for runtime_pm | ||
| 973 | */ | ||
| 974 | par->autosuspend_delay = (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) | ||
| 975 | ? 1000 : 200; | ||
| 976 | |||
| 977 | pm_runtime_set_active(info->device); | ||
| 978 | pm_runtime_enable(info->device); | ||
| 979 | pm_runtime_set_autosuspend_delay(info->device, par->autosuspend_delay); | ||
| 980 | pm_runtime_use_autosuspend(info->device); | ||
| 981 | |||
| 982 | return 0; | ||
| 983 | |||
| 984 | err_sysfs: | ||
| 985 | unregister_framebuffer(info); | ||
| 986 | err_regfb: | ||
| 987 | fb_dealloc_cmap(&info->cmap); | ||
| 988 | err_cmap: | ||
| 989 | fb_deferred_io_cleanup(info); | ||
| 990 | kfree(info->fbdefio); | ||
| 991 | err_defio: | ||
| 992 | vfree((void *)info->screen_base); | ||
| 993 | err_irq: | ||
| 994 | auok190x_power(par, 0); | ||
| 995 | err_gpio3: | ||
| 996 | gpio_free(board->gpio_nrst); | ||
| 997 | err_gpio2: | ||
| 998 | gpio_free(board->gpio_nsleep); | ||
| 999 | err_gpio1: | ||
| 1000 | board->cleanup(par); | ||
| 1001 | err_board: | ||
| 1002 | regulator_put(par->regulator); | ||
| 1003 | err_reg: | ||
| 1004 | framebuffer_release(info); | ||
| 1005 | |||
| 1006 | return ret; | ||
| 1007 | } | ||
| 1008 | EXPORT_SYMBOL_GPL(auok190x_common_probe); | ||
| 1009 | |||
| 1010 | int __devexit auok190x_common_remove(struct platform_device *pdev) | ||
| 1011 | { | ||
| 1012 | struct fb_info *info = platform_get_drvdata(pdev); | ||
| 1013 | struct auok190xfb_par *par = info->par; | ||
| 1014 | struct auok190x_board *board = par->board; | ||
| 1015 | |||
| 1016 | pm_runtime_disable(info->device); | ||
| 1017 | |||
| 1018 | sysfs_remove_group(&info->device->kobj, &auok190x_attr_group); | ||
| 1019 | |||
| 1020 | unregister_framebuffer(info); | ||
| 1021 | |||
| 1022 | fb_dealloc_cmap(&info->cmap); | ||
| 1023 | |||
| 1024 | fb_deferred_io_cleanup(info); | ||
| 1025 | kfree(info->fbdefio); | ||
| 1026 | |||
| 1027 | vfree((void *)info->screen_base); | ||
| 1028 | |||
| 1029 | auok190x_power(par, 0); | ||
| 1030 | |||
| 1031 | gpio_free(board->gpio_nrst); | ||
| 1032 | gpio_free(board->gpio_nsleep); | ||
| 1033 | |||
| 1034 | board->cleanup(par); | ||
| 1035 | |||
| 1036 | regulator_put(par->regulator); | ||
| 1037 | |||
| 1038 | framebuffer_release(info); | ||
| 1039 | |||
| 1040 | return 0; | ||
| 1041 | } | ||
| 1042 | EXPORT_SYMBOL_GPL(auok190x_common_remove); | ||
| 1043 | |||
| 1044 | MODULE_DESCRIPTION("Common code for AUO-K190X controllers"); | ||
| 1045 | MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); | ||
| 1046 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/auo_k190x.h b/drivers/video/auo_k190x.h new file mode 100644 index 000000000000..e35af1f51b28 --- /dev/null +++ b/drivers/video/auo_k190x.h | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | /* | ||
| 2 | * Private common definitions for AUO-K190X framebuffer drivers | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | /* | ||
| 12 | * I80 interface specific defines | ||
| 13 | */ | ||
| 14 | |||
| 15 | #define AUOK190X_I80_CS 0x01 | ||
| 16 | #define AUOK190X_I80_DC 0x02 | ||
| 17 | #define AUOK190X_I80_WR 0x03 | ||
| 18 | #define AUOK190X_I80_OE 0x04 | ||
| 19 | |||
| 20 | /* | ||
| 21 | * AUOK190x commands, common to both controllers | ||
| 22 | */ | ||
| 23 | |||
| 24 | #define AUOK190X_CMD_INIT 0x0000 | ||
| 25 | #define AUOK190X_CMD_STANDBY 0x0001 | ||
| 26 | #define AUOK190X_CMD_WAKEUP 0x0002 | ||
| 27 | #define AUOK190X_CMD_TCON_RESET 0x0003 | ||
| 28 | #define AUOK190X_CMD_DATA_STOP 0x1002 | ||
| 29 | #define AUOK190X_CMD_LUT_START 0x1003 | ||
| 30 | #define AUOK190X_CMD_DISP_REFRESH 0x1004 | ||
| 31 | #define AUOK190X_CMD_DISP_RESET 0x1005 | ||
| 32 | #define AUOK190X_CMD_PRE_DISPLAY_START 0x100D | ||
| 33 | #define AUOK190X_CMD_PRE_DISPLAY_STOP 0x100F | ||
| 34 | #define AUOK190X_CMD_FLASH_W 0x2000 | ||
| 35 | #define AUOK190X_CMD_FLASH_E 0x2001 | ||
| 36 | #define AUOK190X_CMD_FLASH_STS 0x2002 | ||
| 37 | #define AUOK190X_CMD_FRAMERATE 0x3000 | ||
| 38 | #define AUOK190X_CMD_READ_VERSION 0x4000 | ||
| 39 | #define AUOK190X_CMD_READ_STATUS 0x4001 | ||
| 40 | #define AUOK190X_CMD_READ_LUT 0x4003 | ||
| 41 | #define AUOK190X_CMD_DRIVERTIMING 0x5000 | ||
| 42 | #define AUOK190X_CMD_LBALANCE 0x5001 | ||
| 43 | #define AUOK190X_CMD_AGINGMODE 0x6000 | ||
| 44 | #define AUOK190X_CMD_AGINGEXIT 0x6001 | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Common settings for AUOK190X_CMD_INIT | ||
| 48 | */ | ||
| 49 | |||
| 50 | #define AUOK190X_INIT_DATA_FILTER (0 << 12) | ||
| 51 | #define AUOK190X_INIT_DATA_BYPASS (1 << 12) | ||
| 52 | #define AUOK190X_INIT_INVERSE_WHITE (0 << 9) | ||
| 53 | #define AUOK190X_INIT_INVERSE_BLACK (1 << 9) | ||
| 54 | #define AUOK190X_INIT_SCAN_DOWN (0 << 1) | ||
| 55 | #define AUOK190X_INIT_SCAN_UP (1 << 1) | ||
| 56 | #define AUOK190X_INIT_SHIFT_LEFT (0 << 0) | ||
| 57 | #define AUOK190X_INIT_SHIFT_RIGHT (1 << 0) | ||
| 58 | |||
| 59 | /* Common bits to pixels | ||
| 60 | * Mode 15-12 11-8 7-4 3-0 | ||
| 61 | * format0 4 3 2 1 | ||
| 62 | * format1 3 4 1 2 | ||
| 63 | */ | ||
| 64 | |||
| 65 | #define AUOK190X_INIT_FORMAT0 0 | ||
| 66 | #define AUOK190X_INIT_FORMAT1 (1 << 6) | ||
| 67 | |||
| 68 | /* | ||
| 69 | * settings for AUOK190X_CMD_RESET | ||
| 70 | */ | ||
| 71 | |||
| 72 | #define AUOK190X_RESET_TCON (0 << 0) | ||
| 73 | #define AUOK190X_RESET_NORMAL (1 << 0) | ||
| 74 | #define AUOK190X_RESET_PON (1 << 1) | ||
| 75 | |||
| 76 | /* | ||
| 77 | * AUOK190X_CMD_VERSION | ||
| 78 | */ | ||
| 79 | |||
| 80 | #define AUOK190X_VERSION_TEMP_MASK (0x1ff) | ||
| 81 | #define AUOK190X_VERSION_EPD_MASK (0xff) | ||
| 82 | #define AUOK190X_VERSION_SIZE_INT(_val) ((_val & 0xfc00) >> 10) | ||
| 83 | #define AUOK190X_VERSION_SIZE_FLOAT(_val) ((_val & 0x3c0) >> 6) | ||
| 84 | #define AUOK190X_VERSION_MODEL(_val) (_val & 0x3f) | ||
| 85 | #define AUOK190X_VERSION_LUT(_val) (_val & 0xff) | ||
| 86 | #define AUOK190X_VERSION_TCON(_val) ((_val & 0xff00) >> 8) | ||
| 87 | |||
| 88 | /* | ||
| 89 | * update modes for CMD_PARTIALDISP on K1900 and CMD_DDMA on K1901 | ||
| 90 | */ | ||
| 91 | |||
| 92 | #define AUOK190X_UPDATE_MODE(_res) ((_res & 0x7) << 12) | ||
| 93 | #define AUOK190X_UPDATE_NONFLASH (1 << 15) | ||
| 94 | |||
| 95 | /* | ||
| 96 | * track panel specific parameters for common init | ||
| 97 | */ | ||
| 98 | |||
| 99 | struct auok190x_init_data { | ||
| 100 | char *id; | ||
| 101 | struct auok190x_board *board; | ||
| 102 | |||
| 103 | void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2); | ||
| 104 | void (*update_all)(struct auok190xfb_par *par); | ||
| 105 | bool (*need_refresh)(struct auok190xfb_par *par); | ||
| 106 | void (*init)(struct auok190xfb_par *par); | ||
| 107 | }; | ||
| 108 | |||
| 109 | |||
| 110 | extern void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data); | ||
| 111 | extern int auok190x_send_command(struct auok190xfb_par *par, u16 data); | ||
| 112 | extern void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd, | ||
| 113 | int argc, u16 *argv); | ||
| 114 | extern int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd, | ||
| 115 | int argc, u16 *argv); | ||
| 116 | extern void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par, | ||
| 117 | u16 cmd, int argc, u16 *argv, | ||
| 118 | int size, u16 *data); | ||
| 119 | extern int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd, | ||
| 120 | int argc, u16 *argv, int size, | ||
| 121 | u16 *data); | ||
| 122 | extern int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd, | ||
| 123 | int argc, u16 *argv); | ||
| 124 | |||
| 125 | extern int auok190x_common_probe(struct platform_device *pdev, | ||
| 126 | struct auok190x_init_data *init); | ||
| 127 | extern int auok190x_common_remove(struct platform_device *pdev); | ||
| 128 | |||
| 129 | extern const struct dev_pm_ops auok190x_pm; | ||
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c index 1a268a294478..33ea874c87d2 100644 --- a/drivers/video/bfin_adv7393fb.c +++ b/drivers/video/bfin_adv7393fb.c | |||
| @@ -414,14 +414,14 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client, | |||
| 414 | if (ret) { | 414 | if (ret) { |
| 415 | dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n"); | 415 | dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n"); |
| 416 | ret = -EBUSY; | 416 | ret = -EBUSY; |
| 417 | goto out_8; | 417 | goto free_fbdev; |
| 418 | } | 418 | } |
| 419 | } | 419 | } |
| 420 | 420 | ||
| 421 | if (peripheral_request_list(ppi_pins, DRIVER_NAME)) { | 421 | if (peripheral_request_list(ppi_pins, DRIVER_NAME)) { |
| 422 | dev_err(&client->dev, "requesting PPI peripheral failed\n"); | 422 | dev_err(&client->dev, "requesting PPI peripheral failed\n"); |
| 423 | ret = -EFAULT; | 423 | ret = -EFAULT; |
| 424 | goto out_8; | 424 | goto free_gpio; |
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | fbdev->fb_mem = | 427 | fbdev->fb_mem = |
| @@ -432,7 +432,7 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client, | |||
| 432 | dev_err(&client->dev, "couldn't allocate dma buffer (%d bytes)\n", | 432 | dev_err(&client->dev, "couldn't allocate dma buffer (%d bytes)\n", |
| 433 | (u32) fbdev->fb_len); | 433 | (u32) fbdev->fb_len); |
| 434 | ret = -ENOMEM; | 434 | ret = -ENOMEM; |
| 435 | goto out_7; | 435 | goto free_ppi_pins; |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | fbdev->info.screen_base = (void *)fbdev->fb_mem; | 438 | fbdev->info.screen_base = (void *)fbdev->fb_mem; |
| @@ -464,27 +464,27 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client, | |||
| 464 | if (!fbdev->info.pseudo_palette) { | 464 | if (!fbdev->info.pseudo_palette) { |
| 465 | dev_err(&client->dev, "failed to allocate pseudo_palette\n"); | 465 | dev_err(&client->dev, "failed to allocate pseudo_palette\n"); |
| 466 | ret = -ENOMEM; | 466 | ret = -ENOMEM; |
| 467 | goto out_6; | 467 | goto free_fb_mem; |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | if (fb_alloc_cmap(&fbdev->info.cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { | 470 | if (fb_alloc_cmap(&fbdev->info.cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { |
| 471 | dev_err(&client->dev, "failed to allocate colormap (%d entries)\n", | 471 | dev_err(&client->dev, "failed to allocate colormap (%d entries)\n", |
| 472 | BFIN_LCD_NBR_PALETTE_ENTRIES); | 472 | BFIN_LCD_NBR_PALETTE_ENTRIES); |
| 473 | ret = -EFAULT; | 473 | ret = -EFAULT; |
| 474 | goto out_5; | 474 | goto free_palette; |
| 475 | } | 475 | } |
| 476 | 476 | ||
| 477 | if (request_dma(CH_PPI, "BF5xx_PPI_DMA") < 0) { | 477 | if (request_dma(CH_PPI, "BF5xx_PPI_DMA") < 0) { |
| 478 | dev_err(&client->dev, "unable to request PPI DMA\n"); | 478 | dev_err(&client->dev, "unable to request PPI DMA\n"); |
| 479 | ret = -EFAULT; | 479 | ret = -EFAULT; |
| 480 | goto out_4; | 480 | goto free_cmap; |
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, 0, | 483 | if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, 0, |
| 484 | "PPI ERROR", fbdev) < 0) { | 484 | "PPI ERROR", fbdev) < 0) { |
| 485 | dev_err(&client->dev, "unable to request PPI ERROR IRQ\n"); | 485 | dev_err(&client->dev, "unable to request PPI ERROR IRQ\n"); |
| 486 | ret = -EFAULT; | 486 | ret = -EFAULT; |
| 487 | goto out_3; | 487 | goto free_ch_ppi; |
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | fbdev->open = 0; | 490 | fbdev->open = 0; |
| @@ -494,14 +494,14 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client, | |||
| 494 | 494 | ||
| 495 | if (ret) { | 495 | if (ret) { |
| 496 | dev_err(&client->dev, "i2c attach: init error\n"); | 496 | dev_err(&client->dev, "i2c attach: init error\n"); |
| 497 | goto out_1; | 497 | goto free_irq_ppi; |
| 498 | } | 498 | } |
| 499 | 499 | ||
| 500 | 500 | ||
| 501 | if (register_framebuffer(&fbdev->info) < 0) { | 501 | if (register_framebuffer(&fbdev->info) < 0) { |
| 502 | dev_err(&client->dev, "unable to register framebuffer\n"); | 502 | dev_err(&client->dev, "unable to register framebuffer\n"); |
| 503 | ret = -EFAULT; | 503 | ret = -EFAULT; |
| 504 | goto out_1; | 504 | goto free_irq_ppi; |
| 505 | } | 505 | } |
| 506 | 506 | ||
| 507 | dev_info(&client->dev, "fb%d: %s frame buffer device\n", | 507 | dev_info(&client->dev, "fb%d: %s frame buffer device\n", |
| @@ -512,7 +512,7 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client, | |||
| 512 | if (!entry) { | 512 | if (!entry) { |
| 513 | dev_err(&client->dev, "unable to create /proc entry\n"); | 513 | dev_err(&client->dev, "unable to create /proc entry\n"); |
| 514 | ret = -EFAULT; | 514 | ret = -EFAULT; |
| 515 | goto out_0; | 515 | goto free_fb; |
| 516 | } | 516 | } |
| 517 | 517 | ||
| 518 | entry->read_proc = adv7393_read_proc; | 518 | entry->read_proc = adv7393_read_proc; |
| @@ -521,22 +521,25 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client, | |||
| 521 | 521 | ||
| 522 | return 0; | 522 | return 0; |
| 523 | 523 | ||
| 524 | out_0: | 524 | free_fb: |
| 525 | unregister_framebuffer(&fbdev->info); | 525 | unregister_framebuffer(&fbdev->info); |
| 526 | out_1: | 526 | free_irq_ppi: |
| 527 | free_irq(IRQ_PPI_ERROR, fbdev); | 527 | free_irq(IRQ_PPI_ERROR, fbdev); |
| 528 | out_3: | 528 | free_ch_ppi: |
| 529 | free_dma(CH_PPI); | 529 | free_dma(CH_PPI); |
| 530 | out_4: | 530 | free_cmap: |
| 531 | dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, | ||
| 532 | fbdev->dma_handle); | ||
| 533 | out_5: | ||
| 534 | fb_dealloc_cmap(&fbdev->info.cmap); | 531 | fb_dealloc_cmap(&fbdev->info.cmap); |
| 535 | out_6: | 532 | free_palette: |
| 536 | kfree(fbdev->info.pseudo_palette); | 533 | kfree(fbdev->info.pseudo_palette); |
| 537 | out_7: | 534 | free_fb_mem: |
| 535 | dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, | ||
| 536 | fbdev->dma_handle); | ||
| 537 | free_ppi_pins: | ||
| 538 | peripheral_free_list(ppi_pins); | 538 | peripheral_free_list(ppi_pins); |
| 539 | out_8: | 539 | free_gpio: |
| 540 | if (ANOMALY_05000400) | ||
| 541 | gpio_free(P_IDENT(P_PPI0_FS3)); | ||
| 542 | free_fbdev: | ||
| 540 | kfree(fbdev); | 543 | kfree(fbdev); |
| 541 | 544 | ||
| 542 | return ret; | 545 | return ret; |
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index f56699d8122a..eae46f6457e2 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Cobalt server LCD frame buffer driver. | 2 | * Cobalt/SEAD3 LCD frame buffer driver. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> | 4 | * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> |
| 5 | * Copyright (C) 2012 MIPS Technologies, Inc. | ||
| 5 | * | 6 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
| @@ -62,6 +63,7 @@ | |||
| 62 | #define LCD_CUR_POS(x) ((x) & LCD_CUR_POS_MASK) | 63 | #define LCD_CUR_POS(x) ((x) & LCD_CUR_POS_MASK) |
| 63 | #define LCD_TEXT_POS(x) ((x) | LCD_TEXT_MODE) | 64 | #define LCD_TEXT_POS(x) ((x) | LCD_TEXT_MODE) |
| 64 | 65 | ||
| 66 | #ifdef CONFIG_MIPS_COBALT | ||
| 65 | static inline void lcd_write_control(struct fb_info *info, u8 control) | 67 | static inline void lcd_write_control(struct fb_info *info, u8 control) |
| 66 | { | 68 | { |
| 67 | writel((u32)control << 24, info->screen_base); | 69 | writel((u32)control << 24, info->screen_base); |
| @@ -81,6 +83,47 @@ static inline u8 lcd_read_data(struct fb_info *info) | |||
| 81 | { | 83 | { |
| 82 | return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24; | 84 | return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24; |
| 83 | } | 85 | } |
| 86 | #else | ||
| 87 | |||
| 88 | #define LCD_CTL 0x00 | ||
| 89 | #define LCD_DATA 0x08 | ||
| 90 | #define CPLD_STATUS 0x10 | ||
| 91 | #define CPLD_DATA 0x18 | ||
| 92 | |||
| 93 | static inline void cpld_wait(struct fb_info *info) | ||
| 94 | { | ||
| 95 | do { | ||
| 96 | } while (readl(info->screen_base + CPLD_STATUS) & 1); | ||
| 97 | } | ||
| 98 | |||
| 99 | static inline void lcd_write_control(struct fb_info *info, u8 control) | ||
| 100 | { | ||
| 101 | cpld_wait(info); | ||
| 102 | writel(control, info->screen_base + LCD_CTL); | ||
| 103 | } | ||
| 104 | |||
| 105 | static inline u8 lcd_read_control(struct fb_info *info) | ||
| 106 | { | ||
| 107 | cpld_wait(info); | ||
| 108 | readl(info->screen_base + LCD_CTL); | ||
| 109 | cpld_wait(info); | ||
| 110 | return readl(info->screen_base + CPLD_DATA) & 0xff; | ||
| 111 | } | ||
| 112 | |||
| 113 | static inline void lcd_write_data(struct fb_info *info, u8 data) | ||
| 114 | { | ||
| 115 | cpld_wait(info); | ||
| 116 | writel(data, info->screen_base + LCD_DATA); | ||
| 117 | } | ||
| 118 | |||
| 119 | static inline u8 lcd_read_data(struct fb_info *info) | ||
| 120 | { | ||
| 121 | cpld_wait(info); | ||
| 122 | readl(info->screen_base + LCD_DATA); | ||
| 123 | cpld_wait(info); | ||
| 124 | return readl(info->screen_base + CPLD_DATA) & 0xff; | ||
| 125 | } | ||
| 126 | #endif | ||
| 84 | 127 | ||
| 85 | static int lcd_busy_wait(struct fb_info *info) | 128 | static int lcd_busy_wait(struct fb_info *info) |
| 86 | { | 129 | { |
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c index f8babbeee275..345d96230978 100644 --- a/drivers/video/ep93xx-fb.c +++ b/drivers/video/ep93xx-fb.c | |||
| @@ -507,16 +507,16 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev) | |||
| 507 | 507 | ||
| 508 | err = fb_alloc_cmap(&info->cmap, 256, 0); | 508 | err = fb_alloc_cmap(&info->cmap, 256, 0); |
| 509 | if (err) | 509 | if (err) |
| 510 | goto failed; | 510 | goto failed_cmap; |
| 511 | 511 | ||
| 512 | err = ep93xxfb_alloc_videomem(info); | 512 | err = ep93xxfb_alloc_videomem(info); |
| 513 | if (err) | 513 | if (err) |
| 514 | goto failed; | 514 | goto failed_videomem; |
| 515 | 515 | ||
| 516 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 516 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 517 | if (!res) { | 517 | if (!res) { |
| 518 | err = -ENXIO; | 518 | err = -ENXIO; |
| 519 | goto failed; | 519 | goto failed_resource; |
| 520 | } | 520 | } |
| 521 | 521 | ||
| 522 | /* | 522 | /* |
| @@ -532,7 +532,7 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev) | |||
| 532 | fbi->mmio_base = ioremap(res->start, resource_size(res)); | 532 | fbi->mmio_base = ioremap(res->start, resource_size(res)); |
| 533 | if (!fbi->mmio_base) { | 533 | if (!fbi->mmio_base) { |
| 534 | err = -ENXIO; | 534 | err = -ENXIO; |
| 535 | goto failed; | 535 | goto failed_resource; |
| 536 | } | 536 | } |
| 537 | 537 | ||
| 538 | strcpy(info->fix.id, pdev->name); | 538 | strcpy(info->fix.id, pdev->name); |
| @@ -553,24 +553,24 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev) | |||
| 553 | if (err == 0) { | 553 | if (err == 0) { |
| 554 | dev_err(info->dev, "No suitable video mode found\n"); | 554 | dev_err(info->dev, "No suitable video mode found\n"); |
| 555 | err = -EINVAL; | 555 | err = -EINVAL; |
| 556 | goto failed; | 556 | goto failed_mode; |
| 557 | } | 557 | } |
| 558 | 558 | ||
| 559 | if (mach_info->setup) { | 559 | if (mach_info->setup) { |
| 560 | err = mach_info->setup(pdev); | 560 | err = mach_info->setup(pdev); |
| 561 | if (err) | 561 | if (err) |
| 562 | return err; | 562 | goto failed_mode; |
| 563 | } | 563 | } |
| 564 | 564 | ||
| 565 | err = ep93xxfb_check_var(&info->var, info); | 565 | err = ep93xxfb_check_var(&info->var, info); |
| 566 | if (err) | 566 | if (err) |
| 567 | goto failed; | 567 | goto failed_check; |
| 568 | 568 | ||
| 569 | fbi->clk = clk_get(info->dev, NULL); | 569 | fbi->clk = clk_get(info->dev, NULL); |
| 570 | if (IS_ERR(fbi->clk)) { | 570 | if (IS_ERR(fbi->clk)) { |
| 571 | err = PTR_ERR(fbi->clk); | 571 | err = PTR_ERR(fbi->clk); |
| 572 | fbi->clk = NULL; | 572 | fbi->clk = NULL; |
| 573 | goto failed; | 573 | goto failed_check; |
| 574 | } | 574 | } |
| 575 | 575 | ||
| 576 | ep93xxfb_set_par(info); | 576 | ep93xxfb_set_par(info); |
| @@ -585,15 +585,17 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev) | |||
| 585 | return 0; | 585 | return 0; |
| 586 | 586 | ||
| 587 | failed: | 587 | failed: |
| 588 | if (fbi->clk) | 588 | clk_put(fbi->clk); |
| 589 | clk_put(fbi->clk); | 589 | failed_check: |
| 590 | if (fbi->mmio_base) | ||
| 591 | iounmap(fbi->mmio_base); | ||
| 592 | ep93xxfb_dealloc_videomem(info); | ||
| 593 | if (&info->cmap) | ||
| 594 | fb_dealloc_cmap(&info->cmap); | ||
| 595 | if (fbi->mach_info->teardown) | 590 | if (fbi->mach_info->teardown) |
| 596 | fbi->mach_info->teardown(pdev); | 591 | fbi->mach_info->teardown(pdev); |
| 592 | failed_mode: | ||
| 593 | iounmap(fbi->mmio_base); | ||
| 594 | failed_resource: | ||
| 595 | ep93xxfb_dealloc_videomem(info); | ||
| 596 | failed_videomem: | ||
| 597 | fb_dealloc_cmap(&info->cmap); | ||
| 598 | failed_cmap: | ||
| 597 | kfree(info); | 599 | kfree(info); |
| 598 | platform_set_drvdata(pdev, NULL); | 600 | platform_set_drvdata(pdev, NULL); |
| 599 | 601 | ||
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index 2a4481cf260c..a36b2d28280e 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c | |||
| @@ -21,14 +21,14 @@ | |||
| 21 | 21 | ||
| 22 | #include <video/exynos_dp.h> | 22 | #include <video/exynos_dp.h> |
| 23 | 23 | ||
| 24 | #include <plat/cpu.h> | ||
| 25 | |||
| 26 | #include "exynos_dp_core.h" | 24 | #include "exynos_dp_core.h" |
| 27 | 25 | ||
| 28 | static int exynos_dp_init_dp(struct exynos_dp_device *dp) | 26 | static int exynos_dp_init_dp(struct exynos_dp_device *dp) |
| 29 | { | 27 | { |
| 30 | exynos_dp_reset(dp); | 28 | exynos_dp_reset(dp); |
| 31 | 29 | ||
| 30 | exynos_dp_swreset(dp); | ||
| 31 | |||
| 32 | /* SW defined function Normal operation */ | 32 | /* SW defined function Normal operation */ |
| 33 | exynos_dp_enable_sw_function(dp); | 33 | exynos_dp_enable_sw_function(dp); |
| 34 | 34 | ||
| @@ -478,7 +478,7 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) | |||
| 478 | int lane_count; | 478 | int lane_count; |
| 479 | u8 buf[5]; | 479 | u8 buf[5]; |
| 480 | 480 | ||
| 481 | u8 *adjust_request; | 481 | u8 adjust_request[2]; |
| 482 | u8 voltage_swing; | 482 | u8 voltage_swing; |
| 483 | u8 pre_emphasis; | 483 | u8 pre_emphasis; |
| 484 | u8 training_lane; | 484 | u8 training_lane; |
| @@ -493,8 +493,8 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) | |||
| 493 | /* set training pattern 2 for EQ */ | 493 | /* set training pattern 2 for EQ */ |
| 494 | exynos_dp_set_training_pattern(dp, TRAINING_PTN2); | 494 | exynos_dp_set_training_pattern(dp, TRAINING_PTN2); |
| 495 | 495 | ||
| 496 | adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1 | 496 | adjust_request[0] = link_status[4]; |
| 497 | - DPCD_ADDR_LANE0_1_STATUS); | 497 | adjust_request[1] = link_status[5]; |
| 498 | 498 | ||
| 499 | exynos_dp_get_adjust_train(dp, adjust_request); | 499 | exynos_dp_get_adjust_train(dp, adjust_request); |
| 500 | 500 | ||
| @@ -566,7 +566,7 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) | |||
| 566 | u8 buf[5]; | 566 | u8 buf[5]; |
| 567 | u32 reg; | 567 | u32 reg; |
| 568 | 568 | ||
| 569 | u8 *adjust_request; | 569 | u8 adjust_request[2]; |
| 570 | 570 | ||
| 571 | udelay(400); | 571 | udelay(400); |
| 572 | 572 | ||
| @@ -575,8 +575,8 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) | |||
| 575 | lane_count = dp->link_train.lane_count; | 575 | lane_count = dp->link_train.lane_count; |
| 576 | 576 | ||
| 577 | if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { | 577 | if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { |
| 578 | adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1 | 578 | adjust_request[0] = link_status[4]; |
| 579 | - DPCD_ADDR_LANE0_1_STATUS); | 579 | adjust_request[1] = link_status[5]; |
| 580 | 580 | ||
| 581 | if (exynos_dp_channel_eq_ok(link_status, lane_count) == 0) { | 581 | if (exynos_dp_channel_eq_ok(link_status, lane_count) == 0) { |
| 582 | /* traing pattern Set to Normal */ | 582 | /* traing pattern Set to Normal */ |
| @@ -770,7 +770,7 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp, | |||
| 770 | return -ETIMEDOUT; | 770 | return -ETIMEDOUT; |
| 771 | } | 771 | } |
| 772 | 772 | ||
| 773 | mdelay(100); | 773 | udelay(1); |
| 774 | } | 774 | } |
| 775 | 775 | ||
| 776 | /* Set to use the register calculated M/N video */ | 776 | /* Set to use the register calculated M/N video */ |
| @@ -804,7 +804,7 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp, | |||
| 804 | return -ETIMEDOUT; | 804 | return -ETIMEDOUT; |
| 805 | } | 805 | } |
| 806 | 806 | ||
| 807 | mdelay(100); | 807 | mdelay(1); |
| 808 | } | 808 | } |
| 809 | 809 | ||
| 810 | if (retval != 0) | 810 | if (retval != 0) |
| @@ -860,7 +860,8 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) | |||
| 860 | return -EINVAL; | 860 | return -EINVAL; |
| 861 | } | 861 | } |
| 862 | 862 | ||
| 863 | dp = kzalloc(sizeof(struct exynos_dp_device), GFP_KERNEL); | 863 | dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), |
| 864 | GFP_KERNEL); | ||
| 864 | if (!dp) { | 865 | if (!dp) { |
| 865 | dev_err(&pdev->dev, "no memory for device data\n"); | 866 | dev_err(&pdev->dev, "no memory for device data\n"); |
| 866 | return -ENOMEM; | 867 | return -ENOMEM; |
| @@ -871,8 +872,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) | |||
| 871 | dp->clock = clk_get(&pdev->dev, "dp"); | 872 | dp->clock = clk_get(&pdev->dev, "dp"); |
| 872 | if (IS_ERR(dp->clock)) { | 873 | if (IS_ERR(dp->clock)) { |
| 873 | dev_err(&pdev->dev, "failed to get clock\n"); | 874 | dev_err(&pdev->dev, "failed to get clock\n"); |
| 874 | ret = PTR_ERR(dp->clock); | 875 | return PTR_ERR(dp->clock); |
| 875 | goto err_dp; | ||
| 876 | } | 876 | } |
| 877 | 877 | ||
| 878 | clk_enable(dp->clock); | 878 | clk_enable(dp->clock); |
| @@ -884,35 +884,25 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) | |||
| 884 | goto err_clock; | 884 | goto err_clock; |
| 885 | } | 885 | } |
| 886 | 886 | ||
| 887 | res = request_mem_region(res->start, resource_size(res), | 887 | dp->reg_base = devm_request_and_ioremap(&pdev->dev, res); |
| 888 | dev_name(&pdev->dev)); | ||
| 889 | if (!res) { | ||
| 890 | dev_err(&pdev->dev, "failed to request registers region\n"); | ||
| 891 | ret = -EINVAL; | ||
| 892 | goto err_clock; | ||
| 893 | } | ||
| 894 | |||
| 895 | dp->res = res; | ||
| 896 | |||
| 897 | dp->reg_base = ioremap(res->start, resource_size(res)); | ||
| 898 | if (!dp->reg_base) { | 888 | if (!dp->reg_base) { |
| 899 | dev_err(&pdev->dev, "failed to ioremap\n"); | 889 | dev_err(&pdev->dev, "failed to ioremap\n"); |
| 900 | ret = -ENOMEM; | 890 | ret = -ENOMEM; |
| 901 | goto err_req_region; | 891 | goto err_clock; |
| 902 | } | 892 | } |
| 903 | 893 | ||
| 904 | dp->irq = platform_get_irq(pdev, 0); | 894 | dp->irq = platform_get_irq(pdev, 0); |
| 905 | if (!dp->irq) { | 895 | if (!dp->irq) { |
| 906 | dev_err(&pdev->dev, "failed to get irq\n"); | 896 | dev_err(&pdev->dev, "failed to get irq\n"); |
| 907 | ret = -ENODEV; | 897 | ret = -ENODEV; |
| 908 | goto err_ioremap; | 898 | goto err_clock; |
| 909 | } | 899 | } |
| 910 | 900 | ||
| 911 | ret = request_irq(dp->irq, exynos_dp_irq_handler, 0, | 901 | ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0, |
| 912 | "exynos-dp", dp); | 902 | "exynos-dp", dp); |
| 913 | if (ret) { | 903 | if (ret) { |
| 914 | dev_err(&pdev->dev, "failed to request irq\n"); | 904 | dev_err(&pdev->dev, "failed to request irq\n"); |
| 915 | goto err_ioremap; | 905 | goto err_clock; |
| 916 | } | 906 | } |
| 917 | 907 | ||
| 918 | dp->video_info = pdata->video_info; | 908 | dp->video_info = pdata->video_info; |
| @@ -924,7 +914,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) | |||
| 924 | ret = exynos_dp_detect_hpd(dp); | 914 | ret = exynos_dp_detect_hpd(dp); |
| 925 | if (ret) { | 915 | if (ret) { |
| 926 | dev_err(&pdev->dev, "unable to detect hpd\n"); | 916 | dev_err(&pdev->dev, "unable to detect hpd\n"); |
| 927 | goto err_irq; | 917 | goto err_clock; |
| 928 | } | 918 | } |
| 929 | 919 | ||
| 930 | exynos_dp_handle_edid(dp); | 920 | exynos_dp_handle_edid(dp); |
| @@ -933,7 +923,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) | |||
| 933 | dp->video_info->link_rate); | 923 | dp->video_info->link_rate); |
| 934 | if (ret) { | 924 | if (ret) { |
| 935 | dev_err(&pdev->dev, "unable to do link train\n"); | 925 | dev_err(&pdev->dev, "unable to do link train\n"); |
| 936 | goto err_irq; | 926 | goto err_clock; |
| 937 | } | 927 | } |
| 938 | 928 | ||
| 939 | exynos_dp_enable_scramble(dp, 1); | 929 | exynos_dp_enable_scramble(dp, 1); |
| @@ -947,23 +937,15 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) | |||
| 947 | ret = exynos_dp_config_video(dp, dp->video_info); | 937 | ret = exynos_dp_config_video(dp, dp->video_info); |
| 948 | if (ret) { | 938 | if (ret) { |
| 949 | dev_err(&pdev->dev, "unable to config video\n"); | 939 | dev_err(&pdev->dev, "unable to config video\n"); |
| 950 | goto err_irq; | 940 | goto err_clock; |
| 951 | } | 941 | } |
| 952 | 942 | ||
| 953 | platform_set_drvdata(pdev, dp); | 943 | platform_set_drvdata(pdev, dp); |
| 954 | 944 | ||
| 955 | return 0; | 945 | return 0; |
| 956 | 946 | ||
| 957 | err_irq: | ||
| 958 | free_irq(dp->irq, dp); | ||
| 959 | err_ioremap: | ||
| 960 | iounmap(dp->reg_base); | ||
| 961 | err_req_region: | ||
| 962 | release_mem_region(res->start, resource_size(res)); | ||
| 963 | err_clock: | 947 | err_clock: |
| 964 | clk_put(dp->clock); | 948 | clk_put(dp->clock); |
| 965 | err_dp: | ||
| 966 | kfree(dp); | ||
| 967 | 949 | ||
| 968 | return ret; | 950 | return ret; |
| 969 | } | 951 | } |
| @@ -976,16 +958,9 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev) | |||
| 976 | if (pdata && pdata->phy_exit) | 958 | if (pdata && pdata->phy_exit) |
| 977 | pdata->phy_exit(); | 959 | pdata->phy_exit(); |
| 978 | 960 | ||
| 979 | free_irq(dp->irq, dp); | ||
| 980 | iounmap(dp->reg_base); | ||
| 981 | |||
| 982 | clk_disable(dp->clock); | 961 | clk_disable(dp->clock); |
| 983 | clk_put(dp->clock); | 962 | clk_put(dp->clock); |
| 984 | 963 | ||
| 985 | release_mem_region(dp->res->start, resource_size(dp->res)); | ||
| 986 | |||
| 987 | kfree(dp); | ||
| 988 | |||
| 989 | return 0; | 964 | return 0; |
| 990 | } | 965 | } |
| 991 | 966 | ||
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h index 90ceaca0fa24..1e0f998e0c9f 100644 --- a/drivers/video/exynos/exynos_dp_core.h +++ b/drivers/video/exynos/exynos_dp_core.h | |||
| @@ -26,7 +26,6 @@ struct link_train { | |||
| 26 | 26 | ||
| 27 | struct exynos_dp_device { | 27 | struct exynos_dp_device { |
| 28 | struct device *dev; | 28 | struct device *dev; |
| 29 | struct resource *res; | ||
| 30 | struct clk *clock; | 29 | struct clk *clock; |
| 31 | unsigned int irq; | 30 | unsigned int irq; |
| 32 | void __iomem *reg_base; | 31 | void __iomem *reg_base; |
| @@ -39,8 +38,10 @@ struct exynos_dp_device { | |||
| 39 | void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable); | 38 | void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable); |
| 40 | void exynos_dp_stop_video(struct exynos_dp_device *dp); | 39 | void exynos_dp_stop_video(struct exynos_dp_device *dp); |
| 41 | void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable); | 40 | void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable); |
| 41 | void exynos_dp_init_analog_param(struct exynos_dp_device *dp); | ||
| 42 | void exynos_dp_init_interrupt(struct exynos_dp_device *dp); | 42 | void exynos_dp_init_interrupt(struct exynos_dp_device *dp); |
| 43 | void exynos_dp_reset(struct exynos_dp_device *dp); | 43 | void exynos_dp_reset(struct exynos_dp_device *dp); |
| 44 | void exynos_dp_swreset(struct exynos_dp_device *dp); | ||
| 44 | void exynos_dp_config_interrupt(struct exynos_dp_device *dp); | 45 | void exynos_dp_config_interrupt(struct exynos_dp_device *dp); |
| 45 | u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp); | 46 | u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp); |
| 46 | void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable); | 47 | void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable); |
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c index 6548afa0e3d2..6ce76d56c3a1 100644 --- a/drivers/video/exynos/exynos_dp_reg.c +++ b/drivers/video/exynos/exynos_dp_reg.c | |||
| @@ -16,8 +16,6 @@ | |||
| 16 | 16 | ||
| 17 | #include <video/exynos_dp.h> | 17 | #include <video/exynos_dp.h> |
| 18 | 18 | ||
| 19 | #include <plat/cpu.h> | ||
| 20 | |||
| 21 | #include "exynos_dp_core.h" | 19 | #include "exynos_dp_core.h" |
| 22 | #include "exynos_dp_reg.h" | 20 | #include "exynos_dp_reg.h" |
| 23 | 21 | ||
| @@ -65,6 +63,28 @@ void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable) | |||
| 65 | writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP); | 63 | writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP); |
| 66 | } | 64 | } |
| 67 | 65 | ||
| 66 | void exynos_dp_init_analog_param(struct exynos_dp_device *dp) | ||
| 67 | { | ||
| 68 | u32 reg; | ||
| 69 | |||
| 70 | reg = TX_TERMINAL_CTRL_50_OHM; | ||
| 71 | writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1); | ||
| 72 | |||
| 73 | reg = SEL_24M | TX_DVDD_BIT_1_0625V; | ||
| 74 | writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2); | ||
| 75 | |||
| 76 | reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO; | ||
| 77 | writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3); | ||
| 78 | |||
| 79 | reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM | | ||
| 80 | TX_CUR1_2X | TX_CUR_8_MA; | ||
| 81 | writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1); | ||
| 82 | |||
| 83 | reg = CH3_AMP_400_MV | CH2_AMP_400_MV | | ||
| 84 | CH1_AMP_400_MV | CH0_AMP_400_MV; | ||
| 85 | writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL); | ||
| 86 | } | ||
| 87 | |||
| 68 | void exynos_dp_init_interrupt(struct exynos_dp_device *dp) | 88 | void exynos_dp_init_interrupt(struct exynos_dp_device *dp) |
| 69 | { | 89 | { |
| 70 | /* Set interrupt pin assertion polarity as high */ | 90 | /* Set interrupt pin assertion polarity as high */ |
| @@ -89,8 +109,6 @@ void exynos_dp_reset(struct exynos_dp_device *dp) | |||
| 89 | { | 109 | { |
| 90 | u32 reg; | 110 | u32 reg; |
| 91 | 111 | ||
| 92 | writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET); | ||
| 93 | |||
| 94 | exynos_dp_stop_video(dp); | 112 | exynos_dp_stop_video(dp); |
| 95 | exynos_dp_enable_video_mute(dp, 0); | 113 | exynos_dp_enable_video_mute(dp, 0); |
| 96 | 114 | ||
| @@ -131,9 +149,15 @@ void exynos_dp_reset(struct exynos_dp_device *dp) | |||
| 131 | 149 | ||
| 132 | writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); | 150 | writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); |
| 133 | 151 | ||
| 152 | exynos_dp_init_analog_param(dp); | ||
| 134 | exynos_dp_init_interrupt(dp); | 153 | exynos_dp_init_interrupt(dp); |
| 135 | } | 154 | } |
| 136 | 155 | ||
| 156 | void exynos_dp_swreset(struct exynos_dp_device *dp) | ||
| 157 | { | ||
| 158 | writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET); | ||
| 159 | } | ||
| 160 | |||
| 137 | void exynos_dp_config_interrupt(struct exynos_dp_device *dp) | 161 | void exynos_dp_config_interrupt(struct exynos_dp_device *dp) |
| 138 | { | 162 | { |
| 139 | u32 reg; | 163 | u32 reg; |
| @@ -271,6 +295,7 @@ void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp, | |||
| 271 | void exynos_dp_init_analog_func(struct exynos_dp_device *dp) | 295 | void exynos_dp_init_analog_func(struct exynos_dp_device *dp) |
| 272 | { | 296 | { |
| 273 | u32 reg; | 297 | u32 reg; |
| 298 | int timeout_loop = 0; | ||
| 274 | 299 | ||
| 275 | exynos_dp_set_analog_power_down(dp, POWER_ALL, 0); | 300 | exynos_dp_set_analog_power_down(dp, POWER_ALL, 0); |
| 276 | 301 | ||
| @@ -282,9 +307,19 @@ void exynos_dp_init_analog_func(struct exynos_dp_device *dp) | |||
| 282 | writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL); | 307 | writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL); |
| 283 | 308 | ||
| 284 | /* Power up PLL */ | 309 | /* Power up PLL */ |
| 285 | if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) | 310 | if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { |
| 286 | exynos_dp_set_pll_power_down(dp, 0); | 311 | exynos_dp_set_pll_power_down(dp, 0); |
| 287 | 312 | ||
| 313 | while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { | ||
| 314 | timeout_loop++; | ||
| 315 | if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { | ||
| 316 | dev_err(dp->dev, "failed to get pll lock status\n"); | ||
| 317 | return; | ||
| 318 | } | ||
| 319 | usleep_range(10, 20); | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 288 | /* Enable Serdes FIFO function and Link symbol clock domain module */ | 323 | /* Enable Serdes FIFO function and Link symbol clock domain module */ |
| 289 | reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2); | 324 | reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2); |
| 290 | reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N | 325 | reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N |
diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h index 42f608e2a43e..125b27cd57ae 100644 --- a/drivers/video/exynos/exynos_dp_reg.h +++ b/drivers/video/exynos/exynos_dp_reg.h | |||
| @@ -24,6 +24,12 @@ | |||
| 24 | 24 | ||
| 25 | #define EXYNOS_DP_LANE_MAP 0x35C | 25 | #define EXYNOS_DP_LANE_MAP 0x35C |
| 26 | 26 | ||
| 27 | #define EXYNOS_DP_ANALOG_CTL_1 0x370 | ||
| 28 | #define EXYNOS_DP_ANALOG_CTL_2 0x374 | ||
| 29 | #define EXYNOS_DP_ANALOG_CTL_3 0x378 | ||
| 30 | #define EXYNOS_DP_PLL_FILTER_CTL_1 0x37C | ||
| 31 | #define EXYNOS_DP_TX_AMP_TUNING_CTL 0x380 | ||
| 32 | |||
| 27 | #define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390 | 33 | #define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390 |
| 28 | 34 | ||
| 29 | #define EXYNOS_DP_COMMON_INT_STA_1 0x3C4 | 35 | #define EXYNOS_DP_COMMON_INT_STA_1 0x3C4 |
| @@ -166,6 +172,29 @@ | |||
| 166 | #define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0) | 172 | #define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0) |
| 167 | #define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0) | 173 | #define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0) |
| 168 | 174 | ||
| 175 | /* EXYNOS_DP_ANALOG_CTL_1 */ | ||
| 176 | #define TX_TERMINAL_CTRL_50_OHM (0x1 << 4) | ||
| 177 | |||
| 178 | /* EXYNOS_DP_ANALOG_CTL_2 */ | ||
| 179 | #define SEL_24M (0x1 << 3) | ||
| 180 | #define TX_DVDD_BIT_1_0625V (0x4 << 0) | ||
| 181 | |||
| 182 | /* EXYNOS_DP_ANALOG_CTL_3 */ | ||
| 183 | #define DRIVE_DVDD_BIT_1_0625V (0x4 << 5) | ||
| 184 | #define VCO_BIT_600_MICRO (0x5 << 0) | ||
| 185 | |||
| 186 | /* EXYNOS_DP_PLL_FILTER_CTL_1 */ | ||
| 187 | #define PD_RING_OSC (0x1 << 6) | ||
| 188 | #define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4) | ||
| 189 | #define TX_CUR1_2X (0x1 << 2) | ||
| 190 | #define TX_CUR_8_MA (0x2 << 0) | ||
| 191 | |||
| 192 | /* EXYNOS_DP_TX_AMP_TUNING_CTL */ | ||
| 193 | #define CH3_AMP_400_MV (0x0 << 24) | ||
| 194 | #define CH2_AMP_400_MV (0x0 << 16) | ||
| 195 | #define CH1_AMP_400_MV (0x0 << 8) | ||
| 196 | #define CH0_AMP_400_MV (0x0 << 0) | ||
| 197 | |||
| 169 | /* EXYNOS_DP_AUX_HW_RETRY_CTL */ | 198 | /* EXYNOS_DP_AUX_HW_RETRY_CTL */ |
| 170 | #define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8) | 199 | #define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8) |
| 171 | #define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3) | 200 | #define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3) |
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index 557091dc0e97..6c1f5c314a42 100644 --- a/drivers/video/exynos/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c | |||
| @@ -58,7 +58,7 @@ static struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device | |||
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | static struct regulator_bulk_data supplies[] = { | 60 | static struct regulator_bulk_data supplies[] = { |
| 61 | { .supply = "vdd10", }, | 61 | { .supply = "vdd11", }, |
| 62 | { .supply = "vdd18", }, | 62 | { .supply = "vdd18", }, |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| @@ -102,6 +102,8 @@ static void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim) | |||
| 102 | /* set display timing. */ | 102 | /* set display timing. */ |
| 103 | exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config); | 103 | exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config); |
| 104 | 104 | ||
| 105 | exynos_mipi_dsi_init_interrupt(dsim); | ||
| 106 | |||
| 105 | /* | 107 | /* |
| 106 | * data from Display controller(FIMD) is transferred in video mode | 108 | * data from Display controller(FIMD) is transferred in video mode |
| 107 | * but in case of command mode, all settigs is updated to registers. | 109 | * but in case of command mode, all settigs is updated to registers. |
| @@ -413,27 +415,30 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) | |||
| 413 | goto err_platform_get_irq; | 415 | goto err_platform_get_irq; |
| 414 | } | 416 | } |
| 415 | 417 | ||
| 418 | init_completion(&dsim_wr_comp); | ||
| 419 | init_completion(&dsim_rd_comp); | ||
| 420 | platform_set_drvdata(pdev, dsim); | ||
| 421 | |||
| 416 | ret = request_irq(dsim->irq, exynos_mipi_dsi_interrupt_handler, | 422 | ret = request_irq(dsim->irq, exynos_mipi_dsi_interrupt_handler, |
| 417 | IRQF_SHARED, pdev->name, dsim); | 423 | IRQF_SHARED, dev_name(&pdev->dev), dsim); |
| 418 | if (ret != 0) { | 424 | if (ret != 0) { |
| 419 | dev_err(&pdev->dev, "failed to request dsim irq\n"); | 425 | dev_err(&pdev->dev, "failed to request dsim irq\n"); |
| 420 | ret = -EINVAL; | 426 | ret = -EINVAL; |
| 421 | goto err_bind; | 427 | goto err_bind; |
| 422 | } | 428 | } |
| 423 | 429 | ||
| 424 | init_completion(&dsim_wr_comp); | 430 | /* enable interrupts */ |
| 425 | init_completion(&dsim_rd_comp); | ||
| 426 | |||
| 427 | /* enable interrupt */ | ||
| 428 | exynos_mipi_dsi_init_interrupt(dsim); | 431 | exynos_mipi_dsi_init_interrupt(dsim); |
| 429 | 432 | ||
| 430 | /* initialize mipi-dsi client(lcd panel). */ | 433 | /* initialize mipi-dsi client(lcd panel). */ |
| 431 | if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe) | 434 | if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe) |
| 432 | dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev); | 435 | dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev); |
| 433 | 436 | ||
| 434 | /* in case that mipi got enabled at bootloader. */ | 437 | /* in case mipi-dsi has been enabled by bootloader */ |
| 435 | if (dsim_pd->enabled) | 438 | if (dsim_pd->enabled) { |
| 436 | goto out; | 439 | exynos_mipi_regulator_enable(dsim); |
| 440 | goto done; | ||
| 441 | } | ||
| 437 | 442 | ||
| 438 | /* lcd panel power on. */ | 443 | /* lcd panel power on. */ |
| 439 | if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on) | 444 | if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on) |
| @@ -453,12 +458,11 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) | |||
| 453 | 458 | ||
| 454 | dsim->suspended = false; | 459 | dsim->suspended = false; |
| 455 | 460 | ||
| 456 | out: | 461 | done: |
| 457 | platform_set_drvdata(pdev, dsim); | 462 | platform_set_drvdata(pdev, dsim); |
| 458 | 463 | ||
| 459 | dev_dbg(&pdev->dev, "mipi-dsi driver(%s mode) has been probed.\n", | 464 | dev_dbg(&pdev->dev, "%s() completed sucessfuly (%s mode)\n", __func__, |
| 460 | (dsim_config->e_interface == DSIM_COMMAND) ? | 465 | dsim_config->e_interface == DSIM_COMMAND ? "CPU" : "RGB"); |
| 461 | "CPU" : "RGB"); | ||
| 462 | 466 | ||
| 463 | return 0; | 467 | return 0; |
| 464 | 468 | ||
| @@ -515,10 +519,10 @@ static int __devexit exynos_mipi_dsi_remove(struct platform_device *pdev) | |||
| 515 | return 0; | 519 | return 0; |
| 516 | } | 520 | } |
| 517 | 521 | ||
| 518 | #ifdef CONFIG_PM | 522 | #ifdef CONFIG_PM_SLEEP |
| 519 | static int exynos_mipi_dsi_suspend(struct platform_device *pdev, | 523 | static int exynos_mipi_dsi_suspend(struct device *dev) |
| 520 | pm_message_t state) | ||
| 521 | { | 524 | { |
| 525 | struct platform_device *pdev = to_platform_device(dev); | ||
| 522 | struct mipi_dsim_device *dsim = platform_get_drvdata(pdev); | 526 | struct mipi_dsim_device *dsim = platform_get_drvdata(pdev); |
| 523 | struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; | 527 | struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; |
| 524 | struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; | 528 | struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; |
| @@ -544,8 +548,9 @@ static int exynos_mipi_dsi_suspend(struct platform_device *pdev, | |||
| 544 | return 0; | 548 | return 0; |
| 545 | } | 549 | } |
| 546 | 550 | ||
| 547 | static int exynos_mipi_dsi_resume(struct platform_device *pdev) | 551 | static int exynos_mipi_dsi_resume(struct device *dev) |
| 548 | { | 552 | { |
| 553 | struct platform_device *pdev = to_platform_device(dev); | ||
| 549 | struct mipi_dsim_device *dsim = platform_get_drvdata(pdev); | 554 | struct mipi_dsim_device *dsim = platform_get_drvdata(pdev); |
| 550 | struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; | 555 | struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; |
| 551 | struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; | 556 | struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; |
| @@ -577,19 +582,19 @@ static int exynos_mipi_dsi_resume(struct platform_device *pdev) | |||
| 577 | 582 | ||
| 578 | return 0; | 583 | return 0; |
| 579 | } | 584 | } |
| 580 | #else | ||
| 581 | #define exynos_mipi_dsi_suspend NULL | ||
| 582 | #define exynos_mipi_dsi_resume NULL | ||
| 583 | #endif | 585 | #endif |
| 584 | 586 | ||
| 587 | static const struct dev_pm_ops exynos_mipi_dsi_pm_ops = { | ||
| 588 | SET_SYSTEM_SLEEP_PM_OPS(exynos_mipi_dsi_suspend, exynos_mipi_dsi_resume) | ||
| 589 | }; | ||
| 590 | |||
| 585 | static struct platform_driver exynos_mipi_dsi_driver = { | 591 | static struct platform_driver exynos_mipi_dsi_driver = { |
| 586 | .probe = exynos_mipi_dsi_probe, | 592 | .probe = exynos_mipi_dsi_probe, |
| 587 | .remove = __devexit_p(exynos_mipi_dsi_remove), | 593 | .remove = __devexit_p(exynos_mipi_dsi_remove), |
| 588 | .suspend = exynos_mipi_dsi_suspend, | ||
| 589 | .resume = exynos_mipi_dsi_resume, | ||
| 590 | .driver = { | 594 | .driver = { |
| 591 | .name = "exynos-mipi-dsim", | 595 | .name = "exynos-mipi-dsim", |
| 592 | .owner = THIS_MODULE, | 596 | .owner = THIS_MODULE, |
| 597 | .pm = &exynos_mipi_dsi_pm_ops, | ||
| 593 | }, | 598 | }, |
| 594 | }; | 599 | }; |
| 595 | 600 | ||
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c index 14909c1d3832..47b533a183be 100644 --- a/drivers/video/exynos/exynos_mipi_dsi_common.c +++ b/drivers/video/exynos/exynos_mipi_dsi_common.c | |||
| @@ -76,33 +76,25 @@ static unsigned int dpll_table[15] = { | |||
| 76 | 76 | ||
| 77 | irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id) | 77 | irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id) |
| 78 | { | 78 | { |
| 79 | unsigned int intsrc = 0; | 79 | struct mipi_dsim_device *dsim = dev_id; |
| 80 | unsigned int intmsk = 0; | 80 | unsigned int intsrc, intmsk; |
| 81 | struct mipi_dsim_device *dsim = NULL; | 81 | |
| 82 | 82 | if (dsim == NULL) { | |
| 83 | dsim = dev_id; | 83 | dev_err(dsim->dev, "%s: wrong parameter\n", __func__); |
| 84 | if (!dsim) { | 84 | return IRQ_NONE; |
| 85 | dev_dbg(dsim->dev, KERN_ERR "%s:error: wrong parameter\n", | ||
| 86 | __func__); | ||
| 87 | return IRQ_HANDLED; | ||
| 88 | } | 85 | } |
| 89 | 86 | ||
| 90 | intsrc = exynos_mipi_dsi_read_interrupt(dsim); | 87 | intsrc = exynos_mipi_dsi_read_interrupt(dsim); |
| 91 | intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim); | 88 | intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim); |
| 89 | intmsk = ~intmsk & intsrc; | ||
| 92 | 90 | ||
| 93 | intmsk = ~(intmsk) & intsrc; | 91 | if (intsrc & INTMSK_RX_DONE) { |
| 94 | |||
| 95 | switch (intmsk) { | ||
| 96 | case INTMSK_RX_DONE: | ||
| 97 | complete(&dsim_rd_comp); | 92 | complete(&dsim_rd_comp); |
| 98 | dev_dbg(dsim->dev, "MIPI INTMSK_RX_DONE\n"); | 93 | dev_dbg(dsim->dev, "MIPI INTMSK_RX_DONE\n"); |
| 99 | break; | 94 | } |
| 100 | case INTMSK_FIFO_EMPTY: | 95 | if (intsrc & INTMSK_FIFO_EMPTY) { |
| 101 | complete(&dsim_wr_comp); | 96 | complete(&dsim_wr_comp); |
| 102 | dev_dbg(dsim->dev, "MIPI INTMSK_FIFO_EMPTY\n"); | 97 | dev_dbg(dsim->dev, "MIPI INTMSK_FIFO_EMPTY\n"); |
| 103 | break; | ||
| 104 | default: | ||
| 105 | break; | ||
| 106 | } | 98 | } |
| 107 | 99 | ||
| 108 | exynos_mipi_dsi_clear_interrupt(dsim, intmsk); | 100 | exynos_mipi_dsi_clear_interrupt(dsim, intmsk); |
| @@ -738,11 +730,11 @@ int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim, | |||
| 738 | if (dsim_config->auto_vertical_cnt == 0) { | 730 | if (dsim_config->auto_vertical_cnt == 0) { |
| 739 | exynos_mipi_dsi_set_main_disp_vporch(dsim, | 731 | exynos_mipi_dsi_set_main_disp_vporch(dsim, |
| 740 | dsim_config->cmd_allow, | 732 | dsim_config->cmd_allow, |
| 741 | timing->upper_margin, | 733 | timing->lower_margin, |
| 742 | timing->lower_margin); | 734 | timing->upper_margin); |
| 743 | exynos_mipi_dsi_set_main_disp_hporch(dsim, | 735 | exynos_mipi_dsi_set_main_disp_hporch(dsim, |
| 744 | timing->left_margin, | 736 | timing->right_margin, |
| 745 | timing->right_margin); | 737 | timing->left_margin); |
| 746 | exynos_mipi_dsi_set_main_disp_sync_area(dsim, | 738 | exynos_mipi_dsi_set_main_disp_sync_area(dsim, |
| 747 | timing->vsync_len, | 739 | timing->vsync_len, |
| 748 | timing->hsync_len); | 740 | timing->hsync_len); |
diff --git a/drivers/video/exynos/s6e8ax0.c b/drivers/video/exynos/s6e8ax0.c index 4aa9ac6218bf..05d080b63bc0 100644 --- a/drivers/video/exynos/s6e8ax0.c +++ b/drivers/video/exynos/s6e8ax0.c | |||
| @@ -293,9 +293,20 @@ static void s6e8ax0_panel_cond(struct s6e8ax0 *lcd) | |||
| 293 | 0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0, | 293 | 0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0, |
| 294 | 0xc8, 0x08, 0x48, 0xc1, 0x00, 0xc1, 0xff, 0xff, 0xc8 | 294 | 0xc8, 0x08, 0x48, 0xc1, 0x00, 0xc1, 0xff, 0xff, 0xc8 |
| 295 | }; | 295 | }; |
| 296 | static const unsigned char data_to_send_panel_reverse[] = { | ||
| 297 | 0xf8, 0x19, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3c, 0x7d, | ||
| 298 | 0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08, | ||
| 299 | 0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0, | ||
| 300 | 0xc1, 0x01, 0x41, 0xc1, 0x00, 0xc1, 0xf6, 0xf6, 0xc1 | ||
| 301 | }; | ||
| 296 | 302 | ||
| 297 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | 303 | if (lcd->dsim_dev->panel_reverse) |
| 298 | data_to_send, ARRAY_SIZE(data_to_send)); | 304 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, |
| 305 | data_to_send_panel_reverse, | ||
| 306 | ARRAY_SIZE(data_to_send_panel_reverse)); | ||
| 307 | else | ||
| 308 | ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE, | ||
| 309 | data_to_send, ARRAY_SIZE(data_to_send)); | ||
| 299 | } | 310 | } |
| 300 | 311 | ||
| 301 | static void s6e8ax0_display_cond(struct s6e8ax0 *lcd) | 312 | static void s6e8ax0_display_cond(struct s6e8ax0 *lcd) |
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index c27e153d8882..1ddeb11659d4 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include <linux/rmap.h> | 23 | #include <linux/rmap.h> |
| 24 | #include <linux/pagemap.h> | 24 | #include <linux/pagemap.h> |
| 25 | 25 | ||
| 26 | struct page *fb_deferred_io_page(struct fb_info *info, unsigned long offs) | 26 | static struct page *fb_deferred_io_page(struct fb_info *info, unsigned long offs) |
| 27 | { | 27 | { |
| 28 | void *screen_base = (void __force *) info->screen_base; | 28 | void *screen_base = (void __force *) info->screen_base; |
| 29 | struct page *page; | 29 | struct page *page; |
| @@ -107,6 +107,10 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, | |||
| 107 | /* protect against the workqueue changing the page list */ | 107 | /* protect against the workqueue changing the page list */ |
| 108 | mutex_lock(&fbdefio->lock); | 108 | mutex_lock(&fbdefio->lock); |
| 109 | 109 | ||
| 110 | /* first write in this cycle, notify the driver */ | ||
| 111 | if (fbdefio->first_io && list_empty(&fbdefio->pagelist)) | ||
| 112 | fbdefio->first_io(info); | ||
| 113 | |||
| 110 | /* | 114 | /* |
| 111 | * We want the page to remain locked from ->page_mkwrite until | 115 | * We want the page to remain locked from ->page_mkwrite until |
| 112 | * the PTE is marked dirty to avoid page_mkclean() being called | 116 | * the PTE is marked dirty to avoid page_mkclean() being called |
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 67afa9c2289d..a55e3669d135 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c | |||
| @@ -80,6 +80,8 @@ EXPORT_SYMBOL(framebuffer_alloc); | |||
| 80 | */ | 80 | */ |
| 81 | void framebuffer_release(struct fb_info *info) | 81 | void framebuffer_release(struct fb_info *info) |
| 82 | { | 82 | { |
| 83 | if (!info) | ||
| 84 | return; | ||
| 83 | kfree(info->apertures); | 85 | kfree(info->apertures); |
| 84 | kfree(info); | 86 | kfree(info); |
| 85 | } | 87 | } |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 6af3f16754f0..458c00664ade 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
| @@ -834,7 +834,6 @@ static void update_lcdc(struct fb_info *info) | |||
| 834 | diu_ops.set_pixel_clock(var->pixclock); | 834 | diu_ops.set_pixel_clock(var->pixclock); |
| 835 | 835 | ||
| 836 | out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ | 836 | out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ |
| 837 | out_be32(&hw->thresholds, 0x00037800); /* The Thresholds */ | ||
| 838 | out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */ | 837 | out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */ |
| 839 | out_be32(&hw->plut, 0x01F5F666); | 838 | out_be32(&hw->plut, 0x01F5F666); |
| 840 | 839 | ||
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 02fd2263610c..bdcbfbae2777 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c | |||
| @@ -680,6 +680,7 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev, | |||
| 680 | + dinfo->fb.size); | 680 | + dinfo->fb.size); |
| 681 | if (!dinfo->aperture.virtual) { | 681 | if (!dinfo->aperture.virtual) { |
| 682 | ERR_MSG("Cannot remap FB region.\n"); | 682 | ERR_MSG("Cannot remap FB region.\n"); |
| 683 | agp_backend_release(bridge); | ||
| 683 | cleanup(dinfo); | 684 | cleanup(dinfo); |
| 684 | return -ENODEV; | 685 | return -ENODEV; |
| 685 | } | 686 | } |
| @@ -689,6 +690,7 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev, | |||
| 689 | INTEL_REG_SIZE); | 690 | INTEL_REG_SIZE); |
| 690 | if (!dinfo->mmio_base) { | 691 | if (!dinfo->mmio_base) { |
| 691 | ERR_MSG("Cannot remap MMIO region.\n"); | 692 | ERR_MSG("Cannot remap MMIO region.\n"); |
| 693 | agp_backend_release(bridge); | ||
| 692 | cleanup(dinfo); | 694 | cleanup(dinfo); |
| 693 | return -ENODEV; | 695 | return -ENODEV; |
| 694 | } | 696 | } |
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c index 273769bb8deb..c87e17afb3e2 100644 --- a/drivers/video/mb862xx/mb862xx-i2c.c +++ b/drivers/video/mb862xx/mb862xx-i2c.c | |||
| @@ -68,7 +68,7 @@ static int mb862xx_i2c_read_byte(struct i2c_adapter *adap, u8 *byte, int last) | |||
| 68 | return 1; | 68 | return 1; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void mb862xx_i2c_stop(struct i2c_adapter *adap) | 71 | static void mb862xx_i2c_stop(struct i2c_adapter *adap) |
| 72 | { | 72 | { |
| 73 | struct mb862xxfb_par *par = adap->algo_data; | 73 | struct mb862xxfb_par *par = adap->algo_data; |
| 74 | 74 | ||
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c index 11a7a333701d..00ce1f34b496 100644 --- a/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c | |||
| @@ -579,7 +579,7 @@ static ssize_t mb862xxfb_show_dispregs(struct device *dev, | |||
| 579 | 579 | ||
| 580 | static DEVICE_ATTR(dispregs, 0444, mb862xxfb_show_dispregs, NULL); | 580 | static DEVICE_ATTR(dispregs, 0444, mb862xxfb_show_dispregs, NULL); |
| 581 | 581 | ||
| 582 | irqreturn_t mb862xx_intr(int irq, void *dev_id) | 582 | static irqreturn_t mb862xx_intr(int irq, void *dev_id) |
| 583 | { | 583 | { |
| 584 | struct mb862xxfb_par *par = (struct mb862xxfb_par *) dev_id; | 584 | struct mb862xxfb_par *par = (struct mb862xxfb_par *) dev_id; |
| 585 | unsigned long reg_ist, mask; | 585 | unsigned long reg_ist, mask; |
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c index 55bf6196b7a0..ab0a8e527333 100644 --- a/drivers/video/mbx/mbxfb.c +++ b/drivers/video/mbx/mbxfb.c | |||
| @@ -950,7 +950,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev) | |||
| 950 | 950 | ||
| 951 | mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr, | 951 | mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr, |
| 952 | res_size(mfbi->fb_req)); | 952 | res_size(mfbi->fb_req)); |
| 953 | if (!mfbi->reg_virt_addr) { | 953 | if (!mfbi->fb_virt_addr) { |
| 954 | dev_err(&dev->dev, "failed to ioremap frame buffer\n"); | 954 | dev_err(&dev->dev, "failed to ioremap frame buffer\n"); |
| 955 | ret = -EINVAL; | 955 | ret = -EINVAL; |
| 956 | goto err4; | 956 | goto err4; |
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 6c6bc578d0fc..abbe691047bd 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c | |||
| @@ -889,6 +889,18 @@ static int __devexit mxsfb_remove(struct platform_device *pdev) | |||
| 889 | return 0; | 889 | return 0; |
| 890 | } | 890 | } |
| 891 | 891 | ||
| 892 | static void mxsfb_shutdown(struct platform_device *pdev) | ||
| 893 | { | ||
| 894 | struct fb_info *fb_info = platform_get_drvdata(pdev); | ||
| 895 | struct mxsfb_info *host = to_imxfb_host(fb_info); | ||
| 896 | |||
| 897 | /* | ||
| 898 | * Force stop the LCD controller as keeping it running during reboot | ||
| 899 | * might interfere with the BootROM's boot mode pads sampling. | ||
| 900 | */ | ||
| 901 | writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR); | ||
| 902 | } | ||
| 903 | |||
| 892 | static struct platform_device_id mxsfb_devtype[] = { | 904 | static struct platform_device_id mxsfb_devtype[] = { |
| 893 | { | 905 | { |
| 894 | .name = "imx23-fb", | 906 | .name = "imx23-fb", |
| @@ -905,6 +917,7 @@ MODULE_DEVICE_TABLE(platform, mxsfb_devtype); | |||
| 905 | static struct platform_driver mxsfb_driver = { | 917 | static struct platform_driver mxsfb_driver = { |
| 906 | .probe = mxsfb_probe, | 918 | .probe = mxsfb_probe, |
| 907 | .remove = __devexit_p(mxsfb_remove), | 919 | .remove = __devexit_p(mxsfb_remove), |
| 920 | .shutdown = mxsfb_shutdown, | ||
| 908 | .id_table = mxsfb_devtype, | 921 | .id_table = mxsfb_devtype, |
| 909 | .driver = { | 922 | .driver = { |
| 910 | .name = DRIVER_NAME, | 923 | .name = DRIVER_NAME, |
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 1e7536d9a8fc..b48f95f0dfe2 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig | |||
| @@ -39,14 +39,6 @@ config FB_OMAP_LCD_MIPID | |||
| 39 | the Mobile Industry Processor Interface DBI-C/DCS | 39 | the Mobile Industry Processor Interface DBI-C/DCS |
| 40 | specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3) | 40 | specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3) |
| 41 | 41 | ||
| 42 | config FB_OMAP_BOOTLOADER_INIT | ||
| 43 | bool "Check bootloader initialization" | ||
| 44 | depends on FB_OMAP | ||
| 45 | help | ||
| 46 | Say Y here if you want to enable checking if the bootloader has | ||
| 47 | already initialized the display controller. In this case the | ||
| 48 | driver will skip the initialization. | ||
| 49 | |||
| 50 | config FB_OMAP_CONSISTENT_DMA_SIZE | 42 | config FB_OMAP_CONSISTENT_DMA_SIZE |
| 51 | int "Consistent DMA memory size (MB)" | 43 | int "Consistent DMA memory size (MB)" |
| 52 | depends on FB_OMAP | 44 | depends on FB_OMAP |
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c index 74e7cf078505..ad741c3d1ae1 100644 --- a/drivers/video/omap2/displays/panel-acx565akm.c +++ b/drivers/video/omap2/displays/panel-acx565akm.c | |||
| @@ -739,12 +739,6 @@ static void acx_panel_set_timings(struct omap_dss_device *dssdev, | |||
| 739 | } | 739 | } |
| 740 | } | 740 | } |
| 741 | 741 | ||
| 742 | static void acx_panel_get_timings(struct omap_dss_device *dssdev, | ||
| 743 | struct omap_video_timings *timings) | ||
| 744 | { | ||
| 745 | *timings = dssdev->panel.timings; | ||
| 746 | } | ||
| 747 | |||
| 748 | static int acx_panel_check_timings(struct omap_dss_device *dssdev, | 742 | static int acx_panel_check_timings(struct omap_dss_device *dssdev, |
| 749 | struct omap_video_timings *timings) | 743 | struct omap_video_timings *timings) |
| 750 | { | 744 | { |
| @@ -762,7 +756,6 @@ static struct omap_dss_driver acx_panel_driver = { | |||
| 762 | .resume = acx_panel_resume, | 756 | .resume = acx_panel_resume, |
| 763 | 757 | ||
| 764 | .set_timings = acx_panel_set_timings, | 758 | .set_timings = acx_panel_set_timings, |
| 765 | .get_timings = acx_panel_get_timings, | ||
| 766 | .check_timings = acx_panel_check_timings, | 759 | .check_timings = acx_panel_check_timings, |
| 767 | 760 | ||
| 768 | .get_recommended_bpp = acx_get_recommended_bpp, | 761 | .get_recommended_bpp = acx_get_recommended_bpp, |
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 30fe4dfeb227..e42f9dc22123 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c | |||
| @@ -386,6 +386,106 @@ static struct panel_config generic_dpi_panels[] = { | |||
| 386 | 386 | ||
| 387 | .name = "innolux_at080tn52", | 387 | .name = "innolux_at080tn52", |
| 388 | }, | 388 | }, |
| 389 | |||
| 390 | /* Mitsubishi AA084SB01 */ | ||
| 391 | { | ||
| 392 | { | ||
| 393 | .x_res = 800, | ||
| 394 | .y_res = 600, | ||
| 395 | .pixel_clock = 40000, | ||
| 396 | |||
| 397 | .hsw = 1, | ||
| 398 | .hfp = 254, | ||
| 399 | .hbp = 1, | ||
| 400 | |||
| 401 | .vsw = 1, | ||
| 402 | .vfp = 26, | ||
| 403 | .vbp = 1, | ||
| 404 | }, | ||
| 405 | .config = OMAP_DSS_LCD_TFT, | ||
| 406 | .name = "mitsubishi_aa084sb01", | ||
| 407 | }, | ||
| 408 | /* EDT ET0500G0DH6 */ | ||
| 409 | { | ||
| 410 | { | ||
| 411 | .x_res = 800, | ||
| 412 | .y_res = 480, | ||
| 413 | .pixel_clock = 33260, | ||
| 414 | |||
| 415 | .hsw = 128, | ||
| 416 | .hfp = 216, | ||
| 417 | .hbp = 40, | ||
| 418 | |||
| 419 | .vsw = 2, | ||
| 420 | .vfp = 35, | ||
| 421 | .vbp = 10, | ||
| 422 | }, | ||
| 423 | .config = OMAP_DSS_LCD_TFT, | ||
| 424 | .name = "edt_et0500g0dh6", | ||
| 425 | }, | ||
| 426 | |||
| 427 | /* Prime-View PD050VL1 */ | ||
| 428 | { | ||
| 429 | { | ||
| 430 | .x_res = 640, | ||
| 431 | .y_res = 480, | ||
| 432 | |||
| 433 | .pixel_clock = 25000, | ||
| 434 | |||
| 435 | .hsw = 96, | ||
| 436 | .hfp = 18, | ||
| 437 | .hbp = 46, | ||
| 438 | |||
| 439 | .vsw = 2, | ||
| 440 | .vfp = 10, | ||
| 441 | .vbp = 33, | ||
| 442 | }, | ||
| 443 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
| 444 | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC, | ||
| 445 | .name = "primeview_pd050vl1", | ||
| 446 | }, | ||
| 447 | |||
| 448 | /* Prime-View PM070WL4 */ | ||
| 449 | { | ||
| 450 | { | ||
| 451 | .x_res = 800, | ||
| 452 | .y_res = 480, | ||
| 453 | |||
| 454 | .pixel_clock = 32000, | ||
| 455 | |||
| 456 | .hsw = 128, | ||
| 457 | .hfp = 42, | ||
| 458 | .hbp = 86, | ||
| 459 | |||
| 460 | .vsw = 2, | ||
| 461 | .vfp = 10, | ||
| 462 | .vbp = 33, | ||
| 463 | }, | ||
| 464 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
| 465 | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC, | ||
| 466 | .name = "primeview_pm070wl4", | ||
| 467 | }, | ||
| 468 | |||
| 469 | /* Prime-View PD104SLF */ | ||
| 470 | { | ||
| 471 | { | ||
| 472 | .x_res = 800, | ||
| 473 | .y_res = 600, | ||
| 474 | |||
| 475 | .pixel_clock = 40000, | ||
| 476 | |||
| 477 | .hsw = 128, | ||
| 478 | .hfp = 42, | ||
| 479 | .hbp = 86, | ||
| 480 | |||
| 481 | .vsw = 4, | ||
| 482 | .vfp = 1, | ||
| 483 | .vbp = 23, | ||
| 484 | }, | ||
| 485 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
| 486 | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC, | ||
| 487 | .name = "primeview_pd104slf", | ||
| 488 | }, | ||
| 389 | }; | 489 | }; |
| 390 | 490 | ||
| 391 | struct panel_drv_data { | 491 | struct panel_drv_data { |
| @@ -549,12 +649,6 @@ static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev, | |||
| 549 | dpi_set_timings(dssdev, timings); | 649 | dpi_set_timings(dssdev, timings); |
| 550 | } | 650 | } |
| 551 | 651 | ||
| 552 | static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev, | ||
| 553 | struct omap_video_timings *timings) | ||
| 554 | { | ||
| 555 | *timings = dssdev->panel.timings; | ||
| 556 | } | ||
| 557 | |||
| 558 | static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, | 652 | static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, |
| 559 | struct omap_video_timings *timings) | 653 | struct omap_video_timings *timings) |
| 560 | { | 654 | { |
| @@ -571,7 +665,6 @@ static struct omap_dss_driver dpi_driver = { | |||
| 571 | .resume = generic_dpi_panel_resume, | 665 | .resume = generic_dpi_panel_resume, |
| 572 | 666 | ||
| 573 | .set_timings = generic_dpi_panel_set_timings, | 667 | .set_timings = generic_dpi_panel_set_timings, |
| 574 | .get_timings = generic_dpi_panel_get_timings, | ||
| 575 | .check_timings = generic_dpi_panel_check_timings, | 668 | .check_timings = generic_dpi_panel_check_timings, |
| 576 | 669 | ||
| 577 | .driver = { | 670 | .driver = { |
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c index dc9408dc93d1..4a34cdc1371b 100644 --- a/drivers/video/omap2/displays/panel-n8x0.c +++ b/drivers/video/omap2/displays/panel-n8x0.c | |||
| @@ -610,12 +610,6 @@ static int n8x0_panel_resume(struct omap_dss_device *dssdev) | |||
| 610 | return 0; | 610 | return 0; |
| 611 | } | 611 | } |
| 612 | 612 | ||
| 613 | static void n8x0_panel_get_timings(struct omap_dss_device *dssdev, | ||
| 614 | struct omap_video_timings *timings) | ||
| 615 | { | ||
| 616 | *timings = dssdev->panel.timings; | ||
| 617 | } | ||
| 618 | |||
| 619 | static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev, | 613 | static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev, |
| 620 | u16 *xres, u16 *yres) | 614 | u16 *xres, u16 *yres) |
| 621 | { | 615 | { |
| @@ -678,8 +672,6 @@ static struct omap_dss_driver n8x0_panel_driver = { | |||
| 678 | .get_resolution = n8x0_panel_get_resolution, | 672 | .get_resolution = n8x0_panel_get_resolution, |
| 679 | .get_recommended_bpp = omapdss_default_get_recommended_bpp, | 673 | .get_recommended_bpp = omapdss_default_get_recommended_bpp, |
| 680 | 674 | ||
| 681 | .get_timings = n8x0_panel_get_timings, | ||
| 682 | |||
| 683 | .driver = { | 675 | .driver = { |
| 684 | .name = "n8x0_panel", | 676 | .name = "n8x0_panel", |
| 685 | .owner = THIS_MODULE, | 677 | .owner = THIS_MODULE, |
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index b2dd88b48420..2ce9992f403b 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <linux/gpio.h> | 30 | #include <linux/gpio.h> |
| 31 | #include <linux/workqueue.h> | 31 | #include <linux/workqueue.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/regulator/consumer.h> | ||
| 34 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
| 35 | 34 | ||
| 36 | #include <video/omapdss.h> | 35 | #include <video/omapdss.h> |
| @@ -55,73 +54,6 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); | |||
| 55 | 54 | ||
| 56 | static int taal_panel_reset(struct omap_dss_device *dssdev); | 55 | static int taal_panel_reset(struct omap_dss_device *dssdev); |
| 57 | 56 | ||
| 58 | struct panel_regulator { | ||
| 59 | struct regulator *regulator; | ||
| 60 | const char *name; | ||
| 61 | int min_uV; | ||
| 62 | int max_uV; | ||
| 63 | }; | ||
| 64 | |||
| 65 | static void free_regulators(struct panel_regulator *regulators, int n) | ||
| 66 | { | ||
| 67 | int i; | ||
| 68 | |||
| 69 | for (i = 0; i < n; i++) { | ||
| 70 | /* disable/put in reverse order */ | ||
| 71 | regulator_disable(regulators[n - i - 1].regulator); | ||
| 72 | regulator_put(regulators[n - i - 1].regulator); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | static int init_regulators(struct omap_dss_device *dssdev, | ||
| 77 | struct panel_regulator *regulators, int n) | ||
| 78 | { | ||
| 79 | int r, i, v; | ||
| 80 | |||
| 81 | for (i = 0; i < n; i++) { | ||
| 82 | struct regulator *reg; | ||
| 83 | |||
| 84 | reg = regulator_get(&dssdev->dev, regulators[i].name); | ||
| 85 | if (IS_ERR(reg)) { | ||
| 86 | dev_err(&dssdev->dev, "failed to get regulator %s\n", | ||
| 87 | regulators[i].name); | ||
| 88 | r = PTR_ERR(reg); | ||
| 89 | goto err; | ||
| 90 | } | ||
| 91 | |||
| 92 | /* FIXME: better handling of fixed vs. variable regulators */ | ||
| 93 | v = regulator_get_voltage(reg); | ||
| 94 | if (v < regulators[i].min_uV || v > regulators[i].max_uV) { | ||
| 95 | r = regulator_set_voltage(reg, regulators[i].min_uV, | ||
| 96 | regulators[i].max_uV); | ||
| 97 | if (r) { | ||
| 98 | dev_err(&dssdev->dev, | ||
| 99 | "failed to set regulator %s voltage\n", | ||
| 100 | regulators[i].name); | ||
| 101 | regulator_put(reg); | ||
| 102 | goto err; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | r = regulator_enable(reg); | ||
| 107 | if (r) { | ||
| 108 | dev_err(&dssdev->dev, "failed to enable regulator %s\n", | ||
| 109 | regulators[i].name); | ||
| 110 | regulator_put(reg); | ||
| 111 | goto err; | ||
| 112 | } | ||
| 113 | |||
| 114 | regulators[i].regulator = reg; | ||
| 115 | } | ||
| 116 | |||
| 117 | return 0; | ||
| 118 | |||
| 119 | err: | ||
| 120 | free_regulators(regulators, i); | ||
| 121 | |||
| 122 | return r; | ||
| 123 | } | ||
| 124 | |||
| 125 | /** | 57 | /** |
| 126 | * struct panel_config - panel configuration | 58 | * struct panel_config - panel configuration |
| 127 | * @name: panel name | 59 | * @name: panel name |
| @@ -150,8 +82,6 @@ struct panel_config { | |||
| 150 | unsigned int low; | 82 | unsigned int low; |
| 151 | } reset_sequence; | 83 | } reset_sequence; |
| 152 | 84 | ||
| 153 | struct panel_regulator *regulators; | ||
| 154 | int num_regulators; | ||
| 155 | }; | 85 | }; |
| 156 | 86 | ||
| 157 | enum { | 87 | enum { |
| @@ -577,12 +507,6 @@ static const struct backlight_ops taal_bl_ops = { | |||
| 577 | .update_status = taal_bl_update_status, | 507 | .update_status = taal_bl_update_status, |
| 578 | }; | 508 | }; |
| 579 | 509 | ||
| 580 | static void taal_get_timings(struct omap_dss_device *dssdev, | ||
| 581 | struct omap_video_timings *timings) | ||
| 582 | { | ||
| 583 | *timings = dssdev->panel.timings; | ||
| 584 | } | ||
| 585 | |||
| 586 | static void taal_get_resolution(struct omap_dss_device *dssdev, | 510 | static void taal_get_resolution(struct omap_dss_device *dssdev, |
| 587 | u16 *xres, u16 *yres) | 511 | u16 *xres, u16 *yres) |
| 588 | { | 512 | { |
| @@ -977,11 +901,6 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
| 977 | 901 | ||
| 978 | atomic_set(&td->do_update, 0); | 902 | atomic_set(&td->do_update, 0); |
| 979 | 903 | ||
| 980 | r = init_regulators(dssdev, panel_config->regulators, | ||
| 981 | panel_config->num_regulators); | ||
| 982 | if (r) | ||
| 983 | goto err_reg; | ||
| 984 | |||
| 985 | td->workqueue = create_singlethread_workqueue("taal_esd"); | 904 | td->workqueue = create_singlethread_workqueue("taal_esd"); |
| 986 | if (td->workqueue == NULL) { | 905 | if (td->workqueue == NULL) { |
| 987 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); | 906 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); |
| @@ -1087,8 +1006,6 @@ err_bl: | |||
| 1087 | err_rst_gpio: | 1006 | err_rst_gpio: |
| 1088 | destroy_workqueue(td->workqueue); | 1007 | destroy_workqueue(td->workqueue); |
| 1089 | err_wq: | 1008 | err_wq: |
| 1090 | free_regulators(panel_config->regulators, panel_config->num_regulators); | ||
| 1091 | err_reg: | ||
| 1092 | kfree(td); | 1009 | kfree(td); |
| 1093 | err: | 1010 | err: |
| 1094 | return r; | 1011 | return r; |
| @@ -1125,9 +1042,6 @@ static void __exit taal_remove(struct omap_dss_device *dssdev) | |||
| 1125 | /* reset, to be sure that the panel is in a valid state */ | 1042 | /* reset, to be sure that the panel is in a valid state */ |
| 1126 | taal_hw_reset(dssdev); | 1043 | taal_hw_reset(dssdev); |
| 1127 | 1044 | ||
| 1128 | free_regulators(td->panel_config->regulators, | ||
| 1129 | td->panel_config->num_regulators); | ||
| 1130 | |||
| 1131 | if (gpio_is_valid(panel_data->reset_gpio)) | 1045 | if (gpio_is_valid(panel_data->reset_gpio)) |
| 1132 | gpio_free(panel_data->reset_gpio); | 1046 | gpio_free(panel_data->reset_gpio); |
| 1133 | 1047 | ||
| @@ -1909,8 +1823,6 @@ static struct omap_dss_driver taal_driver = { | |||
| 1909 | .run_test = taal_run_test, | 1823 | .run_test = taal_run_test, |
| 1910 | .memory_read = taal_memory_read, | 1824 | .memory_read = taal_memory_read, |
| 1911 | 1825 | ||
| 1912 | .get_timings = taal_get_timings, | ||
| 1913 | |||
| 1914 | .driver = { | 1826 | .driver = { |
| 1915 | .name = "taal", | 1827 | .name = "taal", |
| 1916 | .owner = THIS_MODULE, | 1828 | .owner = THIS_MODULE, |
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c index 52637fa8fda8..bff306e041ca 100644 --- a/drivers/video/omap2/displays/panel-tfp410.c +++ b/drivers/video/omap2/displays/panel-tfp410.c | |||
| @@ -47,13 +47,9 @@ struct panel_drv_data { | |||
| 47 | struct mutex lock; | 47 | struct mutex lock; |
| 48 | 48 | ||
| 49 | int pd_gpio; | 49 | int pd_gpio; |
| 50 | }; | ||
| 51 | 50 | ||
| 52 | static inline struct tfp410_platform_data | 51 | struct i2c_adapter *i2c_adapter; |
| 53 | *get_pdata(const struct omap_dss_device *dssdev) | 52 | }; |
| 54 | { | ||
| 55 | return dssdev->data; | ||
| 56 | } | ||
| 57 | 53 | ||
| 58 | static int tfp410_power_on(struct omap_dss_device *dssdev) | 54 | static int tfp410_power_on(struct omap_dss_device *dssdev) |
| 59 | { | 55 | { |
| @@ -68,7 +64,7 @@ static int tfp410_power_on(struct omap_dss_device *dssdev) | |||
| 68 | goto err0; | 64 | goto err0; |
| 69 | 65 | ||
| 70 | if (gpio_is_valid(ddata->pd_gpio)) | 66 | if (gpio_is_valid(ddata->pd_gpio)) |
| 71 | gpio_set_value(ddata->pd_gpio, 1); | 67 | gpio_set_value_cansleep(ddata->pd_gpio, 1); |
| 72 | 68 | ||
| 73 | return 0; | 69 | return 0; |
| 74 | err0: | 70 | err0: |
| @@ -83,18 +79,18 @@ static void tfp410_power_off(struct omap_dss_device *dssdev) | |||
| 83 | return; | 79 | return; |
| 84 | 80 | ||
| 85 | if (gpio_is_valid(ddata->pd_gpio)) | 81 | if (gpio_is_valid(ddata->pd_gpio)) |
| 86 | gpio_set_value(ddata->pd_gpio, 0); | 82 | gpio_set_value_cansleep(ddata->pd_gpio, 0); |
| 87 | 83 | ||
| 88 | omapdss_dpi_display_disable(dssdev); | 84 | omapdss_dpi_display_disable(dssdev); |
| 89 | } | 85 | } |
| 90 | 86 | ||
| 91 | static int tfp410_probe(struct omap_dss_device *dssdev) | 87 | static int tfp410_probe(struct omap_dss_device *dssdev) |
| 92 | { | 88 | { |
| 93 | struct tfp410_platform_data *pdata = get_pdata(dssdev); | ||
| 94 | struct panel_drv_data *ddata; | 89 | struct panel_drv_data *ddata; |
| 95 | int r; | 90 | int r; |
| 91 | int i2c_bus_num; | ||
| 96 | 92 | ||
| 97 | ddata = kzalloc(sizeof(*ddata), GFP_KERNEL); | 93 | ddata = devm_kzalloc(&dssdev->dev, sizeof(*ddata), GFP_KERNEL); |
| 98 | if (!ddata) | 94 | if (!ddata) |
| 99 | return -ENOMEM; | 95 | return -ENOMEM; |
| 100 | 96 | ||
| @@ -104,10 +100,15 @@ static int tfp410_probe(struct omap_dss_device *dssdev) | |||
| 104 | ddata->dssdev = dssdev; | 100 | ddata->dssdev = dssdev; |
| 105 | mutex_init(&ddata->lock); | 101 | mutex_init(&ddata->lock); |
| 106 | 102 | ||
| 107 | if (pdata) | 103 | if (dssdev->data) { |
| 104 | struct tfp410_platform_data *pdata = dssdev->data; | ||
| 105 | |||
| 108 | ddata->pd_gpio = pdata->power_down_gpio; | 106 | ddata->pd_gpio = pdata->power_down_gpio; |
| 109 | else | 107 | i2c_bus_num = pdata->i2c_bus_num; |
| 108 | } else { | ||
| 110 | ddata->pd_gpio = -1; | 109 | ddata->pd_gpio = -1; |
| 110 | i2c_bus_num = -1; | ||
| 111 | } | ||
| 111 | 112 | ||
| 112 | if (gpio_is_valid(ddata->pd_gpio)) { | 113 | if (gpio_is_valid(ddata->pd_gpio)) { |
| 113 | r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW, | 114 | r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW, |
| @@ -115,13 +116,31 @@ static int tfp410_probe(struct omap_dss_device *dssdev) | |||
| 115 | if (r) { | 116 | if (r) { |
| 116 | dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n", | 117 | dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n", |
| 117 | ddata->pd_gpio); | 118 | ddata->pd_gpio); |
| 118 | ddata->pd_gpio = -1; | 119 | return r; |
| 119 | } | 120 | } |
| 120 | } | 121 | } |
| 121 | 122 | ||
| 123 | if (i2c_bus_num != -1) { | ||
| 124 | struct i2c_adapter *adapter; | ||
| 125 | |||
| 126 | adapter = i2c_get_adapter(i2c_bus_num); | ||
| 127 | if (!adapter) { | ||
| 128 | dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n", | ||
| 129 | i2c_bus_num); | ||
| 130 | r = -EINVAL; | ||
| 131 | goto err_i2c; | ||
| 132 | } | ||
| 133 | |||
| 134 | ddata->i2c_adapter = adapter; | ||
| 135 | } | ||
| 136 | |||
| 122 | dev_set_drvdata(&dssdev->dev, ddata); | 137 | dev_set_drvdata(&dssdev->dev, ddata); |
| 123 | 138 | ||
| 124 | return 0; | 139 | return 0; |
| 140 | err_i2c: | ||
| 141 | if (gpio_is_valid(ddata->pd_gpio)) | ||
| 142 | gpio_free(ddata->pd_gpio); | ||
| 143 | return r; | ||
| 125 | } | 144 | } |
| 126 | 145 | ||
| 127 | static void __exit tfp410_remove(struct omap_dss_device *dssdev) | 146 | static void __exit tfp410_remove(struct omap_dss_device *dssdev) |
| @@ -130,14 +149,15 @@ static void __exit tfp410_remove(struct omap_dss_device *dssdev) | |||
| 130 | 149 | ||
| 131 | mutex_lock(&ddata->lock); | 150 | mutex_lock(&ddata->lock); |
| 132 | 151 | ||
| 152 | if (ddata->i2c_adapter) | ||
| 153 | i2c_put_adapter(ddata->i2c_adapter); | ||
| 154 | |||
| 133 | if (gpio_is_valid(ddata->pd_gpio)) | 155 | if (gpio_is_valid(ddata->pd_gpio)) |
| 134 | gpio_free(ddata->pd_gpio); | 156 | gpio_free(ddata->pd_gpio); |
| 135 | 157 | ||
| 136 | dev_set_drvdata(&dssdev->dev, NULL); | 158 | dev_set_drvdata(&dssdev->dev, NULL); |
| 137 | 159 | ||
| 138 | mutex_unlock(&ddata->lock); | 160 | mutex_unlock(&ddata->lock); |
| 139 | |||
| 140 | kfree(ddata); | ||
| 141 | } | 161 | } |
| 142 | 162 | ||
| 143 | static int tfp410_enable(struct omap_dss_device *dssdev) | 163 | static int tfp410_enable(struct omap_dss_device *dssdev) |
| @@ -269,27 +289,17 @@ static int tfp410_read_edid(struct omap_dss_device *dssdev, | |||
| 269 | u8 *edid, int len) | 289 | u8 *edid, int len) |
| 270 | { | 290 | { |
| 271 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | 291 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); |
| 272 | struct tfp410_platform_data *pdata = get_pdata(dssdev); | ||
| 273 | struct i2c_adapter *adapter; | ||
| 274 | int r, l, bytes_read; | 292 | int r, l, bytes_read; |
| 275 | 293 | ||
| 276 | mutex_lock(&ddata->lock); | 294 | mutex_lock(&ddata->lock); |
| 277 | 295 | ||
| 278 | if (pdata->i2c_bus_num == 0) { | 296 | if (!ddata->i2c_adapter) { |
| 279 | r = -ENODEV; | 297 | r = -ENODEV; |
| 280 | goto err; | 298 | goto err; |
| 281 | } | 299 | } |
| 282 | 300 | ||
| 283 | adapter = i2c_get_adapter(pdata->i2c_bus_num); | ||
| 284 | if (!adapter) { | ||
| 285 | dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n", | ||
| 286 | pdata->i2c_bus_num); | ||
| 287 | r = -EINVAL; | ||
| 288 | goto err; | ||
| 289 | } | ||
| 290 | |||
| 291 | l = min(EDID_LENGTH, len); | 301 | l = min(EDID_LENGTH, len); |
| 292 | r = tfp410_ddc_read(adapter, edid, l, 0); | 302 | r = tfp410_ddc_read(ddata->i2c_adapter, edid, l, 0); |
| 293 | if (r) | 303 | if (r) |
| 294 | goto err; | 304 | goto err; |
| 295 | 305 | ||
| @@ -299,7 +309,7 @@ static int tfp410_read_edid(struct omap_dss_device *dssdev, | |||
| 299 | if (len > EDID_LENGTH && edid[0x7e] > 0) { | 309 | if (len > EDID_LENGTH && edid[0x7e] > 0) { |
| 300 | l = min(EDID_LENGTH, len - EDID_LENGTH); | 310 | l = min(EDID_LENGTH, len - EDID_LENGTH); |
| 301 | 311 | ||
| 302 | r = tfp410_ddc_read(adapter, edid + EDID_LENGTH, | 312 | r = tfp410_ddc_read(ddata->i2c_adapter, edid + EDID_LENGTH, |
| 303 | l, EDID_LENGTH); | 313 | l, EDID_LENGTH); |
| 304 | if (r) | 314 | if (r) |
| 305 | goto err; | 315 | goto err; |
| @@ -319,21 +329,15 @@ err: | |||
| 319 | static bool tfp410_detect(struct omap_dss_device *dssdev) | 329 | static bool tfp410_detect(struct omap_dss_device *dssdev) |
| 320 | { | 330 | { |
| 321 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | 331 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); |
| 322 | struct tfp410_platform_data *pdata = get_pdata(dssdev); | ||
| 323 | struct i2c_adapter *adapter; | ||
| 324 | unsigned char out; | 332 | unsigned char out; |
| 325 | int r; | 333 | int r; |
| 326 | 334 | ||
| 327 | mutex_lock(&ddata->lock); | 335 | mutex_lock(&ddata->lock); |
| 328 | 336 | ||
| 329 | if (pdata->i2c_bus_num == 0) | 337 | if (!ddata->i2c_adapter) |
| 330 | goto out; | ||
| 331 | |||
| 332 | adapter = i2c_get_adapter(pdata->i2c_bus_num); | ||
| 333 | if (!adapter) | ||
| 334 | goto out; | 338 | goto out; |
| 335 | 339 | ||
| 336 | r = tfp410_ddc_read(adapter, &out, 1, 0); | 340 | r = tfp410_ddc_read(ddata->i2c_adapter, &out, 1, 0); |
| 337 | 341 | ||
| 338 | mutex_unlock(&ddata->lock); | 342 | mutex_unlock(&ddata->lock); |
| 339 | 343 | ||
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c index 32f3fcd7f0f0..4b6448b3c31f 100644 --- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c | |||
| @@ -272,13 +272,16 @@ static const struct omap_video_timings tpo_td043_timings = { | |||
| 272 | static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) | 272 | static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) |
| 273 | { | 273 | { |
| 274 | int nreset_gpio = tpo_td043->nreset_gpio; | 274 | int nreset_gpio = tpo_td043->nreset_gpio; |
| 275 | int r; | ||
| 275 | 276 | ||
| 276 | if (tpo_td043->powered_on) | 277 | if (tpo_td043->powered_on) |
| 277 | return 0; | 278 | return 0; |
| 278 | 279 | ||
| 279 | regulator_enable(tpo_td043->vcc_reg); | 280 | r = regulator_enable(tpo_td043->vcc_reg); |
| 281 | if (r != 0) | ||
| 282 | return r; | ||
| 280 | 283 | ||
| 281 | /* wait for regulator to stabilize */ | 284 | /* wait for panel to stabilize */ |
| 282 | msleep(160); | 285 | msleep(160); |
| 283 | 286 | ||
| 284 | if (gpio_is_valid(nreset_gpio)) | 287 | if (gpio_is_valid(nreset_gpio)) |
| @@ -470,6 +473,18 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev) | |||
| 470 | gpio_free(nreset_gpio); | 473 | gpio_free(nreset_gpio); |
| 471 | } | 474 | } |
| 472 | 475 | ||
| 476 | static void tpo_td043_set_timings(struct omap_dss_device *dssdev, | ||
| 477 | struct omap_video_timings *timings) | ||
| 478 | { | ||
| 479 | dpi_set_timings(dssdev, timings); | ||
| 480 | } | ||
| 481 | |||
| 482 | static int tpo_td043_check_timings(struct omap_dss_device *dssdev, | ||
| 483 | struct omap_video_timings *timings) | ||
| 484 | { | ||
| 485 | return dpi_check_timings(dssdev, timings); | ||
| 486 | } | ||
| 487 | |||
| 473 | static struct omap_dss_driver tpo_td043_driver = { | 488 | static struct omap_dss_driver tpo_td043_driver = { |
| 474 | .probe = tpo_td043_probe, | 489 | .probe = tpo_td043_probe, |
| 475 | .remove = tpo_td043_remove, | 490 | .remove = tpo_td043_remove, |
| @@ -481,6 +496,9 @@ static struct omap_dss_driver tpo_td043_driver = { | |||
| 481 | .set_mirror = tpo_td043_set_hmirror, | 496 | .set_mirror = tpo_td043_set_hmirror, |
| 482 | .get_mirror = tpo_td043_get_hmirror, | 497 | .get_mirror = tpo_td043_get_hmirror, |
| 483 | 498 | ||
| 499 | .set_timings = tpo_td043_set_timings, | ||
| 500 | .check_timings = tpo_td043_check_timings, | ||
| 501 | |||
| 484 | .driver = { | 502 | .driver = { |
| 485 | .name = "tpo_td043mtea1_panel", | 503 | .name = "tpo_td043mtea1_panel", |
| 486 | .owner = THIS_MODULE, | 504 | .owner = THIS_MODULE, |
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 7be7c06a249e..43324e5ed25f 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig | |||
| @@ -68,6 +68,10 @@ config OMAP4_DSS_HDMI | |||
| 68 | HDMI Interface. This adds the High Definition Multimedia Interface. | 68 | HDMI Interface. This adds the High Definition Multimedia Interface. |
| 69 | See http://www.hdmi.org/ for HDMI specification. | 69 | See http://www.hdmi.org/ for HDMI specification. |
| 70 | 70 | ||
| 71 | config OMAP4_DSS_HDMI_AUDIO | ||
| 72 | bool | ||
| 73 | depends on OMAP4_DSS_HDMI | ||
| 74 | |||
| 71 | config OMAP2_DSS_SDI | 75 | config OMAP2_DSS_SDI |
| 72 | bool "SDI support" | 76 | bool "SDI support" |
| 73 | depends on ARCH_OMAP3 | 77 | depends on ARCH_OMAP3 |
| @@ -90,15 +94,6 @@ config OMAP2_DSS_DSI | |||
| 90 | 94 | ||
| 91 | See http://www.mipi.org/ for DSI spesifications. | 95 | See http://www.mipi.org/ for DSI spesifications. |
| 92 | 96 | ||
| 93 | config OMAP2_DSS_FAKE_VSYNC | ||
| 94 | bool "Fake VSYNC irq from manual update displays" | ||
| 95 | default n | ||
| 96 | help | ||
| 97 | If this is selected, DSI will generate a fake DISPC VSYNC interrupt | ||
| 98 | when DSI has sent a frame. This is only needed with DSI or RFBI | ||
| 99 | displays using manual mode, and you want VSYNC to, for example, | ||
| 100 | time animation. | ||
| 101 | |||
| 102 | config OMAP2_DSS_MIN_FCK_PER_PCK | 97 | config OMAP2_DSS_MIN_FCK_PER_PCK |
| 103 | int "Minimum FCK/PCK ratio (for scaling)" | 98 | int "Minimum FCK/PCK ratio (for scaling)" |
| 104 | range 0 32 | 99 | range 0 32 |
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index b10b3bc1931e..ab22cc224f3e 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c | |||
| @@ -99,6 +99,11 @@ struct mgr_priv_data { | |||
| 99 | 99 | ||
| 100 | /* If true, a display is enabled using this manager */ | 100 | /* If true, a display is enabled using this manager */ |
| 101 | bool enabled; | 101 | bool enabled; |
| 102 | |||
| 103 | bool extra_info_dirty; | ||
| 104 | bool shadow_extra_info_dirty; | ||
| 105 | |||
| 106 | struct omap_video_timings timings; | ||
| 102 | }; | 107 | }; |
| 103 | 108 | ||
| 104 | static struct { | 109 | static struct { |
| @@ -176,7 +181,7 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr) | |||
| 176 | } | 181 | } |
| 177 | 182 | ||
| 178 | static int dss_check_settings_low(struct omap_overlay_manager *mgr, | 183 | static int dss_check_settings_low(struct omap_overlay_manager *mgr, |
| 179 | struct omap_dss_device *dssdev, bool applying) | 184 | bool applying) |
| 180 | { | 185 | { |
| 181 | struct omap_overlay_info *oi; | 186 | struct omap_overlay_info *oi; |
| 182 | struct omap_overlay_manager_info *mi; | 187 | struct omap_overlay_manager_info *mi; |
| @@ -187,6 +192,9 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr, | |||
| 187 | 192 | ||
| 188 | mp = get_mgr_priv(mgr); | 193 | mp = get_mgr_priv(mgr); |
| 189 | 194 | ||
| 195 | if (!mp->enabled) | ||
| 196 | return 0; | ||
| 197 | |||
| 190 | if (applying && mp->user_info_dirty) | 198 | if (applying && mp->user_info_dirty) |
| 191 | mi = &mp->user_info; | 199 | mi = &mp->user_info; |
| 192 | else | 200 | else |
| @@ -206,26 +214,24 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr, | |||
| 206 | ois[ovl->id] = oi; | 214 | ois[ovl->id] = oi; |
| 207 | } | 215 | } |
| 208 | 216 | ||
| 209 | return dss_mgr_check(mgr, dssdev, mi, ois); | 217 | return dss_mgr_check(mgr, mi, &mp->timings, ois); |
| 210 | } | 218 | } |
| 211 | 219 | ||
| 212 | /* | 220 | /* |
| 213 | * check manager and overlay settings using overlay_info from data->info | 221 | * check manager and overlay settings using overlay_info from data->info |
| 214 | */ | 222 | */ |
| 215 | static int dss_check_settings(struct omap_overlay_manager *mgr, | 223 | static int dss_check_settings(struct omap_overlay_manager *mgr) |
| 216 | struct omap_dss_device *dssdev) | ||
| 217 | { | 224 | { |
| 218 | return dss_check_settings_low(mgr, dssdev, false); | 225 | return dss_check_settings_low(mgr, false); |
| 219 | } | 226 | } |
| 220 | 227 | ||
| 221 | /* | 228 | /* |
| 222 | * check manager and overlay settings using overlay_info from ovl->info if | 229 | * check manager and overlay settings using overlay_info from ovl->info if |
| 223 | * dirty and from data->info otherwise | 230 | * dirty and from data->info otherwise |
| 224 | */ | 231 | */ |
| 225 | static int dss_check_settings_apply(struct omap_overlay_manager *mgr, | 232 | static int dss_check_settings_apply(struct omap_overlay_manager *mgr) |
| 226 | struct omap_dss_device *dssdev) | ||
| 227 | { | 233 | { |
| 228 | return dss_check_settings_low(mgr, dssdev, true); | 234 | return dss_check_settings_low(mgr, true); |
| 229 | } | 235 | } |
| 230 | 236 | ||
| 231 | static bool need_isr(void) | 237 | static bool need_isr(void) |
| @@ -261,6 +267,20 @@ static bool need_isr(void) | |||
| 261 | if (mp->shadow_info_dirty) | 267 | if (mp->shadow_info_dirty) |
| 262 | return true; | 268 | return true; |
| 263 | 269 | ||
| 270 | /* | ||
| 271 | * NOTE: we don't check extra_info flags for disabled | ||
| 272 | * managers, once the manager is enabled, the extra_info | ||
| 273 | * related manager changes will be taken in by HW. | ||
| 274 | */ | ||
| 275 | |||
| 276 | /* to write new values to registers */ | ||
| 277 | if (mp->extra_info_dirty) | ||
| 278 | return true; | ||
| 279 | |||
| 280 | /* to set GO bit */ | ||
| 281 | if (mp->shadow_extra_info_dirty) | ||
| 282 | return true; | ||
| 283 | |||
| 264 | list_for_each_entry(ovl, &mgr->overlays, list) { | 284 | list_for_each_entry(ovl, &mgr->overlays, list) { |
| 265 | struct ovl_priv_data *op; | 285 | struct ovl_priv_data *op; |
| 266 | 286 | ||
| @@ -305,7 +325,7 @@ static bool need_go(struct omap_overlay_manager *mgr) | |||
| 305 | 325 | ||
| 306 | mp = get_mgr_priv(mgr); | 326 | mp = get_mgr_priv(mgr); |
| 307 | 327 | ||
| 308 | if (mp->shadow_info_dirty) | 328 | if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty) |
| 309 | return true; | 329 | return true; |
| 310 | 330 | ||
| 311 | list_for_each_entry(ovl, &mgr->overlays, list) { | 331 | list_for_each_entry(ovl, &mgr->overlays, list) { |
| @@ -320,20 +340,16 @@ static bool need_go(struct omap_overlay_manager *mgr) | |||
| 320 | /* returns true if an extra_info field is currently being updated */ | 340 | /* returns true if an extra_info field is currently being updated */ |
| 321 | static bool extra_info_update_ongoing(void) | 341 | static bool extra_info_update_ongoing(void) |
| 322 | { | 342 | { |
| 323 | const int num_ovls = omap_dss_get_num_overlays(); | 343 | const int num_mgrs = dss_feat_get_num_mgrs(); |
| 324 | struct ovl_priv_data *op; | ||
| 325 | struct omap_overlay *ovl; | ||
| 326 | struct mgr_priv_data *mp; | ||
| 327 | int i; | 344 | int i; |
| 328 | 345 | ||
| 329 | for (i = 0; i < num_ovls; ++i) { | 346 | for (i = 0; i < num_mgrs; ++i) { |
| 330 | ovl = omap_dss_get_overlay(i); | 347 | struct omap_overlay_manager *mgr; |
| 331 | op = get_ovl_priv(ovl); | 348 | struct omap_overlay *ovl; |
| 332 | 349 | struct mgr_priv_data *mp; | |
| 333 | if (!ovl->manager) | ||
| 334 | continue; | ||
| 335 | 350 | ||
| 336 | mp = get_mgr_priv(ovl->manager); | 351 | mgr = omap_dss_get_overlay_manager(i); |
| 352 | mp = get_mgr_priv(mgr); | ||
| 337 | 353 | ||
| 338 | if (!mp->enabled) | 354 | if (!mp->enabled) |
| 339 | continue; | 355 | continue; |
| @@ -341,8 +357,15 @@ static bool extra_info_update_ongoing(void) | |||
| 341 | if (!mp->updating) | 357 | if (!mp->updating) |
| 342 | continue; | 358 | continue; |
| 343 | 359 | ||
| 344 | if (op->extra_info_dirty || op->shadow_extra_info_dirty) | 360 | if (mp->extra_info_dirty || mp->shadow_extra_info_dirty) |
| 345 | return true; | 361 | return true; |
| 362 | |||
| 363 | list_for_each_entry(ovl, &mgr->overlays, list) { | ||
| 364 | struct ovl_priv_data *op = get_ovl_priv(ovl); | ||
| 365 | |||
| 366 | if (op->extra_info_dirty || op->shadow_extra_info_dirty) | ||
| 367 | return true; | ||
| 368 | } | ||
| 346 | } | 369 | } |
| 347 | 370 | ||
| 348 | return false; | 371 | return false; |
| @@ -525,11 +548,13 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl) | |||
| 525 | 548 | ||
| 526 | oi = &op->info; | 549 | oi = &op->info; |
| 527 | 550 | ||
| 551 | mp = get_mgr_priv(ovl->manager); | ||
| 552 | |||
| 528 | replication = dss_use_replication(ovl->manager->device, oi->color_mode); | 553 | replication = dss_use_replication(ovl->manager->device, oi->color_mode); |
| 529 | 554 | ||
| 530 | ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC; | 555 | ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC; |
| 531 | 556 | ||
| 532 | r = dispc_ovl_setup(ovl->id, oi, ilace, replication); | 557 | r = dispc_ovl_setup(ovl->id, oi, ilace, replication, &mp->timings); |
| 533 | if (r) { | 558 | if (r) { |
| 534 | /* | 559 | /* |
| 535 | * We can't do much here, as this function can be called from | 560 | * We can't do much here, as this function can be called from |
| @@ -543,8 +568,6 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl) | |||
| 543 | return; | 568 | return; |
| 544 | } | 569 | } |
| 545 | 570 | ||
| 546 | mp = get_mgr_priv(ovl->manager); | ||
| 547 | |||
| 548 | op->info_dirty = false; | 571 | op->info_dirty = false; |
| 549 | if (mp->updating) | 572 | if (mp->updating) |
| 550 | op->shadow_info_dirty = true; | 573 | op->shadow_info_dirty = true; |
| @@ -601,6 +624,22 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr) | |||
| 601 | } | 624 | } |
| 602 | } | 625 | } |
| 603 | 626 | ||
| 627 | static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr) | ||
| 628 | { | ||
| 629 | struct mgr_priv_data *mp = get_mgr_priv(mgr); | ||
| 630 | |||
| 631 | DSSDBGF("%d", mgr->id); | ||
| 632 | |||
| 633 | if (!mp->extra_info_dirty) | ||
| 634 | return; | ||
| 635 | |||
| 636 | dispc_mgr_set_timings(mgr->id, &mp->timings); | ||
| 637 | |||
| 638 | mp->extra_info_dirty = false; | ||
| 639 | if (mp->updating) | ||
| 640 | mp->shadow_extra_info_dirty = true; | ||
| 641 | } | ||
| 642 | |||
| 604 | static void dss_write_regs_common(void) | 643 | static void dss_write_regs_common(void) |
| 605 | { | 644 | { |
| 606 | const int num_mgrs = omap_dss_get_num_overlay_managers(); | 645 | const int num_mgrs = omap_dss_get_num_overlay_managers(); |
| @@ -646,7 +685,7 @@ static void dss_write_regs(void) | |||
| 646 | if (!mp->enabled || mgr_manual_update(mgr) || mp->busy) | 685 | if (!mp->enabled || mgr_manual_update(mgr) || mp->busy) |
| 647 | continue; | 686 | continue; |
| 648 | 687 | ||
| 649 | r = dss_check_settings(mgr, mgr->device); | 688 | r = dss_check_settings(mgr); |
| 650 | if (r) { | 689 | if (r) { |
| 651 | DSSERR("cannot write registers for manager %s: " | 690 | DSSERR("cannot write registers for manager %s: " |
| 652 | "illegal configuration\n", mgr->name); | 691 | "illegal configuration\n", mgr->name); |
| @@ -654,6 +693,7 @@ static void dss_write_regs(void) | |||
| 654 | } | 693 | } |
| 655 | 694 | ||
| 656 | dss_mgr_write_regs(mgr); | 695 | dss_mgr_write_regs(mgr); |
| 696 | dss_mgr_write_regs_extra(mgr); | ||
| 657 | } | 697 | } |
| 658 | } | 698 | } |
| 659 | 699 | ||
| @@ -693,6 +733,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr) | |||
| 693 | 733 | ||
| 694 | mp = get_mgr_priv(mgr); | 734 | mp = get_mgr_priv(mgr); |
| 695 | mp->shadow_info_dirty = false; | 735 | mp->shadow_info_dirty = false; |
| 736 | mp->shadow_extra_info_dirty = false; | ||
| 696 | 737 | ||
| 697 | list_for_each_entry(ovl, &mgr->overlays, list) { | 738 | list_for_each_entry(ovl, &mgr->overlays, list) { |
| 698 | op = get_ovl_priv(ovl); | 739 | op = get_ovl_priv(ovl); |
| @@ -711,7 +752,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr) | |||
| 711 | 752 | ||
| 712 | WARN_ON(mp->updating); | 753 | WARN_ON(mp->updating); |
| 713 | 754 | ||
| 714 | r = dss_check_settings(mgr, mgr->device); | 755 | r = dss_check_settings(mgr); |
| 715 | if (r) { | 756 | if (r) { |
| 716 | DSSERR("cannot start manual update: illegal configuration\n"); | 757 | DSSERR("cannot start manual update: illegal configuration\n"); |
| 717 | spin_unlock_irqrestore(&data_lock, flags); | 758 | spin_unlock_irqrestore(&data_lock, flags); |
| @@ -719,6 +760,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr) | |||
| 719 | } | 760 | } |
| 720 | 761 | ||
| 721 | dss_mgr_write_regs(mgr); | 762 | dss_mgr_write_regs(mgr); |
| 763 | dss_mgr_write_regs_extra(mgr); | ||
| 722 | 764 | ||
| 723 | dss_write_regs_common(); | 765 | dss_write_regs_common(); |
| 724 | 766 | ||
| @@ -857,7 +899,7 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
| 857 | 899 | ||
| 858 | spin_lock_irqsave(&data_lock, flags); | 900 | spin_lock_irqsave(&data_lock, flags); |
| 859 | 901 | ||
| 860 | r = dss_check_settings_apply(mgr, mgr->device); | 902 | r = dss_check_settings_apply(mgr); |
| 861 | if (r) { | 903 | if (r) { |
| 862 | spin_unlock_irqrestore(&data_lock, flags); | 904 | spin_unlock_irqrestore(&data_lock, flags); |
| 863 | DSSERR("failed to apply settings: illegal configuration.\n"); | 905 | DSSERR("failed to apply settings: illegal configuration.\n"); |
| @@ -918,16 +960,13 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl, | |||
| 918 | bool use_fifo_merge) | 960 | bool use_fifo_merge) |
| 919 | { | 961 | { |
| 920 | struct ovl_priv_data *op = get_ovl_priv(ovl); | 962 | struct ovl_priv_data *op = get_ovl_priv(ovl); |
| 921 | struct omap_dss_device *dssdev; | ||
| 922 | u32 fifo_low, fifo_high; | 963 | u32 fifo_low, fifo_high; |
| 923 | 964 | ||
| 924 | if (!op->enabled && !op->enabling) | 965 | if (!op->enabled && !op->enabling) |
| 925 | return; | 966 | return; |
| 926 | 967 | ||
| 927 | dssdev = ovl->manager->device; | ||
| 928 | |||
| 929 | dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high, | 968 | dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high, |
| 930 | use_fifo_merge); | 969 | use_fifo_merge, ovl_manual_update(ovl)); |
| 931 | 970 | ||
| 932 | dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); | 971 | dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); |
| 933 | } | 972 | } |
| @@ -1050,7 +1089,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr) | |||
| 1050 | 1089 | ||
| 1051 | mp->enabled = true; | 1090 | mp->enabled = true; |
| 1052 | 1091 | ||
| 1053 | r = dss_check_settings(mgr, mgr->device); | 1092 | r = dss_check_settings(mgr); |
| 1054 | if (r) { | 1093 | if (r) { |
| 1055 | DSSERR("failed to enable manager %d: check_settings failed\n", | 1094 | DSSERR("failed to enable manager %d: check_settings failed\n", |
| 1056 | mgr->id); | 1095 | mgr->id); |
| @@ -1225,6 +1264,35 @@ err: | |||
| 1225 | return r; | 1264 | return r; |
| 1226 | } | 1265 | } |
| 1227 | 1266 | ||
| 1267 | static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr, | ||
| 1268 | struct omap_video_timings *timings) | ||
| 1269 | { | ||
| 1270 | struct mgr_priv_data *mp = get_mgr_priv(mgr); | ||
| 1271 | |||
| 1272 | mp->timings = *timings; | ||
| 1273 | mp->extra_info_dirty = true; | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | void dss_mgr_set_timings(struct omap_overlay_manager *mgr, | ||
| 1277 | struct omap_video_timings *timings) | ||
| 1278 | { | ||
| 1279 | unsigned long flags; | ||
| 1280 | |||
| 1281 | mutex_lock(&apply_lock); | ||
| 1282 | |||
| 1283 | spin_lock_irqsave(&data_lock, flags); | ||
| 1284 | |||
| 1285 | dss_apply_mgr_timings(mgr, timings); | ||
| 1286 | |||
| 1287 | dss_write_regs(); | ||
| 1288 | dss_set_go_bits(); | ||
| 1289 | |||
| 1290 | spin_unlock_irqrestore(&data_lock, flags); | ||
| 1291 | |||
| 1292 | wait_pending_extra_info_updates(); | ||
| 1293 | |||
| 1294 | mutex_unlock(&apply_lock); | ||
| 1295 | } | ||
| 1228 | 1296 | ||
| 1229 | int dss_ovl_set_info(struct omap_overlay *ovl, | 1297 | int dss_ovl_set_info(struct omap_overlay *ovl, |
| 1230 | struct omap_overlay_info *info) | 1298 | struct omap_overlay_info *info) |
| @@ -1393,7 +1461,7 @@ int dss_ovl_enable(struct omap_overlay *ovl) | |||
| 1393 | 1461 | ||
| 1394 | op->enabling = true; | 1462 | op->enabling = true; |
| 1395 | 1463 | ||
| 1396 | r = dss_check_settings(ovl->manager, ovl->manager->device); | 1464 | r = dss_check_settings(ovl->manager); |
| 1397 | if (r) { | 1465 | if (r) { |
| 1398 | DSSERR("failed to enable overlay %d: check_settings failed\n", | 1466 | DSSERR("failed to enable overlay %d: check_settings failed\n", |
| 1399 | ovl->id); | 1467 | ovl->id); |
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index e8a120771ac6..72ded9cd2cb0 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c | |||
| @@ -43,6 +43,8 @@ static struct { | |||
| 43 | 43 | ||
| 44 | struct regulator *vdds_dsi_reg; | 44 | struct regulator *vdds_dsi_reg; |
| 45 | struct regulator *vdds_sdi_reg; | 45 | struct regulator *vdds_sdi_reg; |
| 46 | |||
| 47 | const char *default_display_name; | ||
| 46 | } core; | 48 | } core; |
| 47 | 49 | ||
| 48 | static char *def_disp_name; | 50 | static char *def_disp_name; |
| @@ -54,9 +56,6 @@ bool dss_debug; | |||
| 54 | module_param_named(debug, dss_debug, bool, 0644); | 56 | module_param_named(debug, dss_debug, bool, 0644); |
| 55 | #endif | 57 | #endif |
| 56 | 58 | ||
| 57 | static int omap_dss_register_device(struct omap_dss_device *); | ||
| 58 | static void omap_dss_unregister_device(struct omap_dss_device *); | ||
| 59 | |||
| 60 | /* REGULATORS */ | 59 | /* REGULATORS */ |
| 61 | 60 | ||
| 62 | struct regulator *dss_get_vdds_dsi(void) | 61 | struct regulator *dss_get_vdds_dsi(void) |
| @@ -87,6 +86,51 @@ struct regulator *dss_get_vdds_sdi(void) | |||
| 87 | return reg; | 86 | return reg; |
| 88 | } | 87 | } |
| 89 | 88 | ||
| 89 | int dss_get_ctx_loss_count(struct device *dev) | ||
| 90 | { | ||
| 91 | struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; | ||
| 92 | int cnt; | ||
| 93 | |||
| 94 | if (!board_data->get_context_loss_count) | ||
| 95 | return -ENOENT; | ||
| 96 | |||
| 97 | cnt = board_data->get_context_loss_count(dev); | ||
| 98 | |||
| 99 | WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt); | ||
| 100 | |||
| 101 | return cnt; | ||
| 102 | } | ||
| 103 | |||
| 104 | int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask) | ||
| 105 | { | ||
| 106 | struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; | ||
| 107 | |||
| 108 | if (!board_data->dsi_enable_pads) | ||
| 109 | return -ENOENT; | ||
| 110 | |||
| 111 | return board_data->dsi_enable_pads(dsi_id, lane_mask); | ||
| 112 | } | ||
| 113 | |||
| 114 | void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask) | ||
| 115 | { | ||
| 116 | struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; | ||
| 117 | |||
| 118 | if (!board_data->dsi_enable_pads) | ||
| 119 | return; | ||
| 120 | |||
| 121 | return board_data->dsi_disable_pads(dsi_id, lane_mask); | ||
| 122 | } | ||
| 123 | |||
| 124 | int dss_set_min_bus_tput(struct device *dev, unsigned long tput) | ||
| 125 | { | ||
| 126 | struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; | ||
| 127 | |||
| 128 | if (pdata->set_min_bus_tput) | ||
| 129 | return pdata->set_min_bus_tput(dev, tput); | ||
| 130 | else | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 90 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | 134 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) |
| 91 | static int dss_debug_show(struct seq_file *s, void *unused) | 135 | static int dss_debug_show(struct seq_file *s, void *unused) |
| 92 | { | 136 | { |
| @@ -121,34 +165,6 @@ static int dss_initialize_debugfs(void) | |||
| 121 | debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, | 165 | debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, |
| 122 | &dss_debug_dump_clocks, &dss_debug_fops); | 166 | &dss_debug_dump_clocks, &dss_debug_fops); |
| 123 | 167 | ||
| 124 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
| 125 | debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir, | ||
| 126 | &dispc_dump_irqs, &dss_debug_fops); | ||
| 127 | #endif | ||
| 128 | |||
| 129 | #if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS) | ||
| 130 | dsi_create_debugfs_files_irq(dss_debugfs_dir, &dss_debug_fops); | ||
| 131 | #endif | ||
| 132 | |||
| 133 | debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, | ||
| 134 | &dss_dump_regs, &dss_debug_fops); | ||
| 135 | debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir, | ||
| 136 | &dispc_dump_regs, &dss_debug_fops); | ||
| 137 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
| 138 | debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir, | ||
| 139 | &rfbi_dump_regs, &dss_debug_fops); | ||
| 140 | #endif | ||
| 141 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
| 142 | dsi_create_debugfs_files_reg(dss_debugfs_dir, &dss_debug_fops); | ||
| 143 | #endif | ||
| 144 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
| 145 | debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, | ||
| 146 | &venc_dump_regs, &dss_debug_fops); | ||
| 147 | #endif | ||
| 148 | #ifdef CONFIG_OMAP4_DSS_HDMI | ||
| 149 | debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir, | ||
| 150 | &hdmi_dump_regs, &dss_debug_fops); | ||
| 151 | #endif | ||
| 152 | return 0; | 168 | return 0; |
| 153 | } | 169 | } |
| 154 | 170 | ||
| @@ -157,6 +173,19 @@ static void dss_uninitialize_debugfs(void) | |||
| 157 | if (dss_debugfs_dir) | 173 | if (dss_debugfs_dir) |
| 158 | debugfs_remove_recursive(dss_debugfs_dir); | 174 | debugfs_remove_recursive(dss_debugfs_dir); |
| 159 | } | 175 | } |
| 176 | |||
| 177 | int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) | ||
| 178 | { | ||
| 179 | struct dentry *d; | ||
| 180 | |||
| 181 | d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, | ||
| 182 | write, &dss_debug_fops); | ||
| 183 | |||
| 184 | if (IS_ERR(d)) | ||
| 185 | return PTR_ERR(d); | ||
| 186 | |||
| 187 | return 0; | ||
| 188 | } | ||
| 160 | #else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ | 189 | #else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ |
| 161 | static inline int dss_initialize_debugfs(void) | 190 | static inline int dss_initialize_debugfs(void) |
| 162 | { | 191 | { |
| @@ -165,14 +194,18 @@ static inline int dss_initialize_debugfs(void) | |||
| 165 | static inline void dss_uninitialize_debugfs(void) | 194 | static inline void dss_uninitialize_debugfs(void) |
| 166 | { | 195 | { |
| 167 | } | 196 | } |
| 197 | static inline int dss_debugfs_create_file(const char *name, | ||
| 198 | void (*write)(struct seq_file *)) | ||
| 199 | { | ||
| 200 | return 0; | ||
| 201 | } | ||
| 168 | #endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ | 202 | #endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ |
| 169 | 203 | ||
| 170 | /* PLATFORM DEVICE */ | 204 | /* PLATFORM DEVICE */ |
| 171 | static int omap_dss_probe(struct platform_device *pdev) | 205 | static int __init omap_dss_probe(struct platform_device *pdev) |
| 172 | { | 206 | { |
| 173 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 207 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
| 174 | int r; | 208 | int r; |
| 175 | int i; | ||
| 176 | 209 | ||
| 177 | core.pdev = pdev; | 210 | core.pdev = pdev; |
| 178 | 211 | ||
| @@ -187,28 +220,13 @@ static int omap_dss_probe(struct platform_device *pdev) | |||
| 187 | if (r) | 220 | if (r) |
| 188 | goto err_debugfs; | 221 | goto err_debugfs; |
| 189 | 222 | ||
| 190 | for (i = 0; i < pdata->num_devices; ++i) { | 223 | if (def_disp_name) |
| 191 | struct omap_dss_device *dssdev = pdata->devices[i]; | 224 | core.default_display_name = def_disp_name; |
| 192 | 225 | else if (pdata->default_device) | |
| 193 | r = omap_dss_register_device(dssdev); | 226 | core.default_display_name = pdata->default_device->name; |
| 194 | if (r) { | ||
| 195 | DSSERR("device %d %s register failed %d\n", i, | ||
| 196 | dssdev->name ?: "unnamed", r); | ||
| 197 | |||
| 198 | while (--i >= 0) | ||
| 199 | omap_dss_unregister_device(pdata->devices[i]); | ||
| 200 | |||
| 201 | goto err_register; | ||
| 202 | } | ||
| 203 | |||
| 204 | if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) | ||
| 205 | pdata->default_device = dssdev; | ||
| 206 | } | ||
| 207 | 227 | ||
| 208 | return 0; | 228 | return 0; |
| 209 | 229 | ||
| 210 | err_register: | ||
| 211 | dss_uninitialize_debugfs(); | ||
| 212 | err_debugfs: | 230 | err_debugfs: |
| 213 | 231 | ||
| 214 | return r; | 232 | return r; |
| @@ -216,17 +234,11 @@ err_debugfs: | |||
| 216 | 234 | ||
| 217 | static int omap_dss_remove(struct platform_device *pdev) | 235 | static int omap_dss_remove(struct platform_device *pdev) |
| 218 | { | 236 | { |
| 219 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | ||
| 220 | int i; | ||
| 221 | |||
| 222 | dss_uninitialize_debugfs(); | 237 | dss_uninitialize_debugfs(); |
| 223 | 238 | ||
| 224 | dss_uninit_overlays(pdev); | 239 | dss_uninit_overlays(pdev); |
| 225 | dss_uninit_overlay_managers(pdev); | 240 | dss_uninit_overlay_managers(pdev); |
| 226 | 241 | ||
| 227 | for (i = 0; i < pdata->num_devices; ++i) | ||
| 228 | omap_dss_unregister_device(pdata->devices[i]); | ||
| 229 | |||
| 230 | return 0; | 242 | return 0; |
| 231 | } | 243 | } |
| 232 | 244 | ||
| @@ -251,7 +263,6 @@ static int omap_dss_resume(struct platform_device *pdev) | |||
| 251 | } | 263 | } |
| 252 | 264 | ||
| 253 | static struct platform_driver omap_dss_driver = { | 265 | static struct platform_driver omap_dss_driver = { |
| 254 | .probe = omap_dss_probe, | ||
| 255 | .remove = omap_dss_remove, | 266 | .remove = omap_dss_remove, |
| 256 | .shutdown = omap_dss_shutdown, | 267 | .shutdown = omap_dss_shutdown, |
| 257 | .suspend = omap_dss_suspend, | 268 | .suspend = omap_dss_suspend, |
| @@ -326,7 +337,6 @@ static int dss_driver_probe(struct device *dev) | |||
| 326 | int r; | 337 | int r; |
| 327 | struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); | 338 | struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); |
| 328 | struct omap_dss_device *dssdev = to_dss_device(dev); | 339 | struct omap_dss_device *dssdev = to_dss_device(dev); |
| 329 | struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; | ||
| 330 | bool force; | 340 | bool force; |
| 331 | 341 | ||
| 332 | DSSDBG("driver_probe: dev %s/%s, drv %s\n", | 342 | DSSDBG("driver_probe: dev %s/%s, drv %s\n", |
| @@ -335,7 +345,8 @@ static int dss_driver_probe(struct device *dev) | |||
| 335 | 345 | ||
| 336 | dss_init_device(core.pdev, dssdev); | 346 | dss_init_device(core.pdev, dssdev); |
| 337 | 347 | ||
| 338 | force = pdata->default_device == dssdev; | 348 | force = core.default_display_name && |
| 349 | strcmp(core.default_display_name, dssdev->name) == 0; | ||
| 339 | dss_recheck_connections(dssdev, force); | 350 | dss_recheck_connections(dssdev, force); |
| 340 | 351 | ||
| 341 | r = dssdrv->probe(dssdev); | 352 | r = dssdrv->probe(dssdev); |
| @@ -381,6 +392,8 @@ int omap_dss_register_driver(struct omap_dss_driver *dssdriver) | |||
| 381 | if (dssdriver->get_recommended_bpp == NULL) | 392 | if (dssdriver->get_recommended_bpp == NULL) |
| 382 | dssdriver->get_recommended_bpp = | 393 | dssdriver->get_recommended_bpp = |
| 383 | omapdss_default_get_recommended_bpp; | 394 | omapdss_default_get_recommended_bpp; |
| 395 | if (dssdriver->get_timings == NULL) | ||
| 396 | dssdriver->get_timings = omapdss_default_get_timings; | ||
| 384 | 397 | ||
| 385 | return driver_register(&dssdriver->driver); | 398 | return driver_register(&dssdriver->driver); |
| 386 | } | 399 | } |
| @@ -427,27 +440,38 @@ static void omap_dss_dev_release(struct device *dev) | |||
| 427 | reset_device(dev, 0); | 440 | reset_device(dev, 0); |
| 428 | } | 441 | } |
| 429 | 442 | ||
| 430 | static int omap_dss_register_device(struct omap_dss_device *dssdev) | 443 | int omap_dss_register_device(struct omap_dss_device *dssdev, |
| 444 | struct device *parent, int disp_num) | ||
| 431 | { | 445 | { |
| 432 | static int dev_num; | ||
| 433 | |||
| 434 | WARN_ON(!dssdev->driver_name); | 446 | WARN_ON(!dssdev->driver_name); |
| 435 | 447 | ||
| 436 | reset_device(&dssdev->dev, 1); | 448 | reset_device(&dssdev->dev, 1); |
| 437 | dssdev->dev.bus = &dss_bus_type; | 449 | dssdev->dev.bus = &dss_bus_type; |
| 438 | dssdev->dev.parent = &dss_bus; | 450 | dssdev->dev.parent = parent; |
| 439 | dssdev->dev.release = omap_dss_dev_release; | 451 | dssdev->dev.release = omap_dss_dev_release; |
| 440 | dev_set_name(&dssdev->dev, "display%d", dev_num++); | 452 | dev_set_name(&dssdev->dev, "display%d", disp_num); |
| 441 | return device_register(&dssdev->dev); | 453 | return device_register(&dssdev->dev); |
| 442 | } | 454 | } |
| 443 | 455 | ||
| 444 | static void omap_dss_unregister_device(struct omap_dss_device *dssdev) | 456 | void omap_dss_unregister_device(struct omap_dss_device *dssdev) |
| 445 | { | 457 | { |
| 446 | device_unregister(&dssdev->dev); | 458 | device_unregister(&dssdev->dev); |
| 447 | } | 459 | } |
| 448 | 460 | ||
| 461 | static int dss_unregister_dss_dev(struct device *dev, void *data) | ||
| 462 | { | ||
| 463 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
| 464 | omap_dss_unregister_device(dssdev); | ||
| 465 | return 0; | ||
| 466 | } | ||
| 467 | |||
| 468 | void omap_dss_unregister_child_devices(struct device *parent) | ||
| 469 | { | ||
| 470 | device_for_each_child(parent, NULL, dss_unregister_dss_dev); | ||
| 471 | } | ||
| 472 | |||
| 449 | /* BUS */ | 473 | /* BUS */ |
| 450 | static int omap_dss_bus_register(void) | 474 | static int __init omap_dss_bus_register(void) |
| 451 | { | 475 | { |
| 452 | int r; | 476 | int r; |
| 453 | 477 | ||
| @@ -469,12 +493,56 @@ static int omap_dss_bus_register(void) | |||
| 469 | } | 493 | } |
| 470 | 494 | ||
| 471 | /* INIT */ | 495 | /* INIT */ |
| 496 | static int (*dss_output_drv_reg_funcs[])(void) __initdata = { | ||
| 497 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
| 498 | dpi_init_platform_driver, | ||
| 499 | #endif | ||
| 500 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
| 501 | sdi_init_platform_driver, | ||
| 502 | #endif | ||
| 503 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
| 504 | rfbi_init_platform_driver, | ||
| 505 | #endif | ||
| 506 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
| 507 | venc_init_platform_driver, | ||
| 508 | #endif | ||
| 509 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
| 510 | dsi_init_platform_driver, | ||
| 511 | #endif | ||
| 512 | #ifdef CONFIG_OMAP4_DSS_HDMI | ||
| 513 | hdmi_init_platform_driver, | ||
| 514 | #endif | ||
| 515 | }; | ||
| 516 | |||
| 517 | static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = { | ||
| 518 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
| 519 | dpi_uninit_platform_driver, | ||
| 520 | #endif | ||
| 521 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
| 522 | sdi_uninit_platform_driver, | ||
| 523 | #endif | ||
| 524 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
| 525 | rfbi_uninit_platform_driver, | ||
| 526 | #endif | ||
| 527 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
| 528 | venc_uninit_platform_driver, | ||
| 529 | #endif | ||
| 530 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
| 531 | dsi_uninit_platform_driver, | ||
| 532 | #endif | ||
| 533 | #ifdef CONFIG_OMAP4_DSS_HDMI | ||
| 534 | hdmi_uninit_platform_driver, | ||
| 535 | #endif | ||
| 536 | }; | ||
| 537 | |||
| 538 | static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)]; | ||
| 472 | 539 | ||
| 473 | static int __init omap_dss_register_drivers(void) | 540 | static int __init omap_dss_register_drivers(void) |
| 474 | { | 541 | { |
| 475 | int r; | 542 | int r; |
| 543 | int i; | ||
| 476 | 544 | ||
| 477 | r = platform_driver_register(&omap_dss_driver); | 545 | r = platform_driver_probe(&omap_dss_driver, omap_dss_probe); |
| 478 | if (r) | 546 | if (r) |
| 479 | return r; | 547 | return r; |
| 480 | 548 | ||
| @@ -490,40 +558,18 @@ static int __init omap_dss_register_drivers(void) | |||
| 490 | goto err_dispc; | 558 | goto err_dispc; |
| 491 | } | 559 | } |
| 492 | 560 | ||
| 493 | r = rfbi_init_platform_driver(); | 561 | /* |
| 494 | if (r) { | 562 | * It's ok if the output-driver register fails. It happens, for example, |
| 495 | DSSERR("Failed to initialize rfbi platform driver\n"); | 563 | * when there is no output-device (e.g. SDI for OMAP4). |
| 496 | goto err_rfbi; | 564 | */ |
| 497 | } | 565 | for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) { |
| 498 | 566 | r = dss_output_drv_reg_funcs[i](); | |
| 499 | r = venc_init_platform_driver(); | 567 | if (r == 0) |
| 500 | if (r) { | 568 | dss_output_drv_loaded[i] = true; |
| 501 | DSSERR("Failed to initialize venc platform driver\n"); | ||
| 502 | goto err_venc; | ||
| 503 | } | ||
| 504 | |||
| 505 | r = dsi_init_platform_driver(); | ||
| 506 | if (r) { | ||
| 507 | DSSERR("Failed to initialize DSI platform driver\n"); | ||
| 508 | goto err_dsi; | ||
| 509 | } | ||
| 510 | |||
| 511 | r = hdmi_init_platform_driver(); | ||
| 512 | if (r) { | ||
| 513 | DSSERR("Failed to initialize hdmi\n"); | ||
| 514 | goto err_hdmi; | ||
| 515 | } | 569 | } |
| 516 | 570 | ||
| 517 | return 0; | 571 | return 0; |
| 518 | 572 | ||
| 519 | err_hdmi: | ||
| 520 | dsi_uninit_platform_driver(); | ||
| 521 | err_dsi: | ||
| 522 | venc_uninit_platform_driver(); | ||
| 523 | err_venc: | ||
| 524 | rfbi_uninit_platform_driver(); | ||
| 525 | err_rfbi: | ||
| 526 | dispc_uninit_platform_driver(); | ||
| 527 | err_dispc: | 573 | err_dispc: |
| 528 | dss_uninit_platform_driver(); | 574 | dss_uninit_platform_driver(); |
| 529 | err_dss: | 575 | err_dss: |
| @@ -534,10 +580,13 @@ err_dss: | |||
| 534 | 580 | ||
| 535 | static void __exit omap_dss_unregister_drivers(void) | 581 | static void __exit omap_dss_unregister_drivers(void) |
| 536 | { | 582 | { |
| 537 | hdmi_uninit_platform_driver(); | 583 | int i; |
| 538 | dsi_uninit_platform_driver(); | 584 | |
| 539 | venc_uninit_platform_driver(); | 585 | for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) { |
| 540 | rfbi_uninit_platform_driver(); | 586 | if (dss_output_drv_loaded[i]) |
| 587 | dss_output_drv_unreg_funcs[i](); | ||
| 588 | } | ||
| 589 | |||
| 541 | dispc_uninit_platform_driver(); | 590 | dispc_uninit_platform_driver(); |
| 542 | dss_uninit_platform_driver(); | 591 | dss_uninit_platform_driver(); |
| 543 | 592 | ||
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index ee30937482e1..4749ac356469 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
| @@ -131,23 +131,6 @@ static inline u32 dispc_read_reg(const u16 idx) | |||
| 131 | return __raw_readl(dispc.base + idx); | 131 | return __raw_readl(dispc.base + idx); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | static int dispc_get_ctx_loss_count(void) | ||
| 135 | { | ||
| 136 | struct device *dev = &dispc.pdev->dev; | ||
| 137 | struct omap_display_platform_data *pdata = dev->platform_data; | ||
| 138 | struct omap_dss_board_info *board_data = pdata->board_data; | ||
| 139 | int cnt; | ||
| 140 | |||
| 141 | if (!board_data->get_context_loss_count) | ||
| 142 | return -ENOENT; | ||
| 143 | |||
| 144 | cnt = board_data->get_context_loss_count(dev); | ||
| 145 | |||
| 146 | WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt); | ||
| 147 | |||
| 148 | return cnt; | ||
| 149 | } | ||
| 150 | |||
| 151 | #define SR(reg) \ | 134 | #define SR(reg) \ |
| 152 | dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) | 135 | dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) |
| 153 | #define RR(reg) \ | 136 | #define RR(reg) \ |
| @@ -251,7 +234,7 @@ static void dispc_save_context(void) | |||
| 251 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | 234 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) |
| 252 | SR(DIVISOR); | 235 | SR(DIVISOR); |
| 253 | 236 | ||
| 254 | dispc.ctx_loss_cnt = dispc_get_ctx_loss_count(); | 237 | dispc.ctx_loss_cnt = dss_get_ctx_loss_count(&dispc.pdev->dev); |
| 255 | dispc.ctx_valid = true; | 238 | dispc.ctx_valid = true; |
| 256 | 239 | ||
| 257 | DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt); | 240 | DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt); |
| @@ -266,7 +249,7 @@ static void dispc_restore_context(void) | |||
| 266 | if (!dispc.ctx_valid) | 249 | if (!dispc.ctx_valid) |
| 267 | return; | 250 | return; |
| 268 | 251 | ||
| 269 | ctx = dispc_get_ctx_loss_count(); | 252 | ctx = dss_get_ctx_loss_count(&dispc.pdev->dev); |
| 270 | 253 | ||
| 271 | if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) | 254 | if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) |
| 272 | return; | 255 | return; |
| @@ -413,14 +396,6 @@ static inline bool dispc_mgr_is_lcd(enum omap_channel channel) | |||
| 413 | return false; | 396 | return false; |
| 414 | } | 397 | } |
| 415 | 398 | ||
| 416 | static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel) | ||
| 417 | { | ||
| 418 | struct omap_overlay_manager *mgr = | ||
| 419 | omap_dss_get_overlay_manager(channel); | ||
| 420 | |||
| 421 | return mgr ? mgr->device : NULL; | ||
| 422 | } | ||
| 423 | |||
| 424 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) | 399 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) |
| 425 | { | 400 | { |
| 426 | switch (channel) { | 401 | switch (channel) { |
| @@ -432,6 +407,7 @@ u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) | |||
| 432 | return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; | 407 | return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; |
| 433 | default: | 408 | default: |
| 434 | BUG(); | 409 | BUG(); |
| 410 | return 0; | ||
| 435 | } | 411 | } |
| 436 | } | 412 | } |
| 437 | 413 | ||
| @@ -446,6 +422,7 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) | |||
| 446 | return 0; | 422 | return 0; |
| 447 | default: | 423 | default: |
| 448 | BUG(); | 424 | BUG(); |
| 425 | return 0; | ||
| 449 | } | 426 | } |
| 450 | } | 427 | } |
| 451 | 428 | ||
| @@ -764,7 +741,7 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane, | |||
| 764 | case OMAP_DSS_COLOR_XRGB16_1555: | 741 | case OMAP_DSS_COLOR_XRGB16_1555: |
| 765 | m = 0xf; break; | 742 | m = 0xf; break; |
| 766 | default: | 743 | default: |
| 767 | BUG(); break; | 744 | BUG(); return; |
| 768 | } | 745 | } |
| 769 | } else { | 746 | } else { |
| 770 | switch (color_mode) { | 747 | switch (color_mode) { |
| @@ -801,13 +778,25 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane, | |||
| 801 | case OMAP_DSS_COLOR_XRGB16_1555: | 778 | case OMAP_DSS_COLOR_XRGB16_1555: |
| 802 | m = 0xf; break; | 779 | m = 0xf; break; |
| 803 | default: | 780 | default: |
| 804 | BUG(); break; | 781 | BUG(); return; |
| 805 | } | 782 | } |
| 806 | } | 783 | } |
| 807 | 784 | ||
| 808 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); | 785 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); |
| 809 | } | 786 | } |
| 810 | 787 | ||
| 788 | static void dispc_ovl_configure_burst_type(enum omap_plane plane, | ||
| 789 | enum omap_dss_rotation_type rotation_type) | ||
| 790 | { | ||
| 791 | if (dss_has_feature(FEAT_BURST_2D) == 0) | ||
| 792 | return; | ||
| 793 | |||
| 794 | if (rotation_type == OMAP_DSS_ROT_TILER) | ||
| 795 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29); | ||
| 796 | else | ||
| 797 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29); | ||
| 798 | } | ||
| 799 | |||
| 811 | void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) | 800 | void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) |
| 812 | { | 801 | { |
| 813 | int shift; | 802 | int shift; |
| @@ -845,6 +834,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) | |||
| 845 | break; | 834 | break; |
| 846 | default: | 835 | default: |
| 847 | BUG(); | 836 | BUG(); |
| 837 | return; | ||
| 848 | } | 838 | } |
| 849 | 839 | ||
| 850 | val = FLD_MOD(val, chan, shift, shift); | 840 | val = FLD_MOD(val, chan, shift, shift); |
| @@ -872,6 +862,7 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) | |||
| 872 | break; | 862 | break; |
| 873 | default: | 863 | default: |
| 874 | BUG(); | 864 | BUG(); |
| 865 | return 0; | ||
| 875 | } | 866 | } |
| 876 | 867 | ||
| 877 | val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); | 868 | val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); |
| @@ -983,20 +974,13 @@ static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) | |||
| 983 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); | 974 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); |
| 984 | } | 975 | } |
| 985 | 976 | ||
| 986 | void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height) | 977 | static void dispc_mgr_set_size(enum omap_channel channel, u16 width, |
| 978 | u16 height) | ||
| 987 | { | 979 | { |
| 988 | u32 val; | 980 | u32 val; |
| 989 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); | ||
| 990 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | ||
| 991 | dispc_write_reg(DISPC_SIZE_MGR(channel), val); | ||
| 992 | } | ||
| 993 | 981 | ||
| 994 | void dispc_set_digit_size(u16 width, u16 height) | ||
| 995 | { | ||
| 996 | u32 val; | ||
| 997 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); | ||
| 998 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 982 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
| 999 | dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val); | 983 | dispc_write_reg(DISPC_SIZE_MGR(channel), val); |
| 1000 | } | 984 | } |
| 1001 | 985 | ||
| 1002 | static void dispc_read_plane_fifo_sizes(void) | 986 | static void dispc_read_plane_fifo_sizes(void) |
| @@ -1063,7 +1047,8 @@ void dispc_enable_fifomerge(bool enable) | |||
| 1063 | } | 1047 | } |
| 1064 | 1048 | ||
| 1065 | void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, | 1049 | void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, |
| 1066 | u32 *fifo_low, u32 *fifo_high, bool use_fifomerge) | 1050 | u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, |
| 1051 | bool manual_update) | ||
| 1067 | { | 1052 | { |
| 1068 | /* | 1053 | /* |
| 1069 | * All sizes are in bytes. Both the buffer and burst are made of | 1054 | * All sizes are in bytes. Both the buffer and burst are made of |
| @@ -1091,7 +1076,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, | |||
| 1091 | * combined fifo size | 1076 | * combined fifo size |
| 1092 | */ | 1077 | */ |
| 1093 | 1078 | ||
| 1094 | if (dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { | 1079 | if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { |
| 1095 | *fifo_low = ovl_fifo_size - burst_size * 2; | 1080 | *fifo_low = ovl_fifo_size - burst_size * 2; |
| 1096 | *fifo_high = total_fifo_size - burst_size; | 1081 | *fifo_high = total_fifo_size - burst_size; |
| 1097 | } else { | 1082 | } else { |
| @@ -1185,6 +1170,94 @@ static void dispc_ovl_set_scale_param(enum omap_plane plane, | |||
| 1185 | dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp); | 1170 | dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp); |
| 1186 | } | 1171 | } |
| 1187 | 1172 | ||
| 1173 | static void dispc_ovl_set_accu_uv(enum omap_plane plane, | ||
| 1174 | u16 orig_width, u16 orig_height, u16 out_width, u16 out_height, | ||
| 1175 | bool ilace, enum omap_color_mode color_mode, u8 rotation) | ||
| 1176 | { | ||
| 1177 | int h_accu2_0, h_accu2_1; | ||
| 1178 | int v_accu2_0, v_accu2_1; | ||
| 1179 | int chroma_hinc, chroma_vinc; | ||
| 1180 | int idx; | ||
| 1181 | |||
| 1182 | struct accu { | ||
| 1183 | s8 h0_m, h0_n; | ||
| 1184 | s8 h1_m, h1_n; | ||
| 1185 | s8 v0_m, v0_n; | ||
| 1186 | s8 v1_m, v1_n; | ||
| 1187 | }; | ||
| 1188 | |||
| 1189 | const struct accu *accu_table; | ||
| 1190 | const struct accu *accu_val; | ||
| 1191 | |||
| 1192 | static const struct accu accu_nv12[4] = { | ||
| 1193 | { 0, 1, 0, 1 , -1, 2, 0, 1 }, | ||
| 1194 | { 1, 2, -3, 4 , 0, 1, 0, 1 }, | ||
| 1195 | { -1, 1, 0, 1 , -1, 2, 0, 1 }, | ||
| 1196 | { -1, 2, -1, 2 , -1, 1, 0, 1 }, | ||
| 1197 | }; | ||
| 1198 | |||
| 1199 | static const struct accu accu_nv12_ilace[4] = { | ||
| 1200 | { 0, 1, 0, 1 , -3, 4, -1, 4 }, | ||
| 1201 | { -1, 4, -3, 4 , 0, 1, 0, 1 }, | ||
| 1202 | { -1, 1, 0, 1 , -1, 4, -3, 4 }, | ||
| 1203 | { -3, 4, -3, 4 , -1, 1, 0, 1 }, | ||
| 1204 | }; | ||
| 1205 | |||
| 1206 | static const struct accu accu_yuv[4] = { | ||
| 1207 | { 0, 1, 0, 1, 0, 1, 0, 1 }, | ||
| 1208 | { 0, 1, 0, 1, 0, 1, 0, 1 }, | ||
| 1209 | { -1, 1, 0, 1, 0, 1, 0, 1 }, | ||
| 1210 | { 0, 1, 0, 1, -1, 1, 0, 1 }, | ||
| 1211 | }; | ||
| 1212 | |||
| 1213 | switch (rotation) { | ||
| 1214 | case OMAP_DSS_ROT_0: | ||
| 1215 | idx = 0; | ||
| 1216 | break; | ||
| 1217 | case OMAP_DSS_ROT_90: | ||
| 1218 | idx = 1; | ||
| 1219 | break; | ||
| 1220 | case OMAP_DSS_ROT_180: | ||
| 1221 | idx = 2; | ||
| 1222 | break; | ||
| 1223 | case OMAP_DSS_ROT_270: | ||
| 1224 | idx = 3; | ||
| 1225 | break; | ||
| 1226 | default: | ||
| 1227 | BUG(); | ||
| 1228 | return; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | switch (color_mode) { | ||
| 1232 | case OMAP_DSS_COLOR_NV12: | ||
| 1233 | if (ilace) | ||
| 1234 | accu_table = accu_nv12_ilace; | ||
| 1235 | else | ||
| 1236 | accu_table = accu_nv12; | ||
| 1237 | break; | ||
| 1238 | case OMAP_DSS_COLOR_YUV2: | ||
| 1239 | case OMAP_DSS_COLOR_UYVY: | ||
| 1240 | accu_table = accu_yuv; | ||
| 1241 | break; | ||
| 1242 | default: | ||
| 1243 | BUG(); | ||
| 1244 | return; | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | accu_val = &accu_table[idx]; | ||
| 1248 | |||
| 1249 | chroma_hinc = 1024 * orig_width / out_width; | ||
| 1250 | chroma_vinc = 1024 * orig_height / out_height; | ||
| 1251 | |||
| 1252 | h_accu2_0 = (accu_val->h0_m * chroma_hinc / accu_val->h0_n) % 1024; | ||
| 1253 | h_accu2_1 = (accu_val->h1_m * chroma_hinc / accu_val->h1_n) % 1024; | ||
| 1254 | v_accu2_0 = (accu_val->v0_m * chroma_vinc / accu_val->v0_n) % 1024; | ||
| 1255 | v_accu2_1 = (accu_val->v1_m * chroma_vinc / accu_val->v1_n) % 1024; | ||
| 1256 | |||
| 1257 | dispc_ovl_set_vid_accu2_0(plane, h_accu2_0, v_accu2_0); | ||
| 1258 | dispc_ovl_set_vid_accu2_1(plane, h_accu2_1, v_accu2_1); | ||
| 1259 | } | ||
| 1260 | |||
| 1188 | static void dispc_ovl_set_scaling_common(enum omap_plane plane, | 1261 | static void dispc_ovl_set_scaling_common(enum omap_plane plane, |
| 1189 | u16 orig_width, u16 orig_height, | 1262 | u16 orig_width, u16 orig_height, |
| 1190 | u16 out_width, u16 out_height, | 1263 | u16 out_width, u16 out_height, |
| @@ -1258,6 +1331,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, | |||
| 1258 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); | 1331 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); |
| 1259 | return; | 1332 | return; |
| 1260 | } | 1333 | } |
| 1334 | |||
| 1335 | dispc_ovl_set_accu_uv(plane, orig_width, orig_height, out_width, | ||
| 1336 | out_height, ilace, color_mode, rotation); | ||
| 1337 | |||
| 1261 | switch (color_mode) { | 1338 | switch (color_mode) { |
| 1262 | case OMAP_DSS_COLOR_NV12: | 1339 | case OMAP_DSS_COLOR_NV12: |
| 1263 | /* UV is subsampled by 2 vertically*/ | 1340 | /* UV is subsampled by 2 vertically*/ |
| @@ -1280,6 +1357,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, | |||
| 1280 | break; | 1357 | break; |
| 1281 | default: | 1358 | default: |
| 1282 | BUG(); | 1359 | BUG(); |
| 1360 | return; | ||
| 1283 | } | 1361 | } |
| 1284 | 1362 | ||
| 1285 | if (out_width != orig_width) | 1363 | if (out_width != orig_width) |
| @@ -1297,9 +1375,6 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, | |||
| 1297 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); | 1375 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); |
| 1298 | /* set V scaling */ | 1376 | /* set V scaling */ |
| 1299 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); | 1377 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); |
| 1300 | |||
| 1301 | dispc_ovl_set_vid_accu2_0(plane, 0x80, 0); | ||
| 1302 | dispc_ovl_set_vid_accu2_1(plane, 0x80, 0); | ||
| 1303 | } | 1378 | } |
| 1304 | 1379 | ||
| 1305 | static void dispc_ovl_set_scaling(enum omap_plane plane, | 1380 | static void dispc_ovl_set_scaling(enum omap_plane plane, |
| @@ -1410,6 +1485,7 @@ static int color_mode_to_bpp(enum omap_color_mode color_mode) | |||
| 1410 | return 32; | 1485 | return 32; |
| 1411 | default: | 1486 | default: |
| 1412 | BUG(); | 1487 | BUG(); |
| 1488 | return 0; | ||
| 1413 | } | 1489 | } |
| 1414 | } | 1490 | } |
| 1415 | 1491 | ||
| @@ -1423,6 +1499,7 @@ static s32 pixinc(int pixels, u8 ps) | |||
| 1423 | return 1 - (-pixels + 1) * ps; | 1499 | return 1 - (-pixels + 1) * ps; |
| 1424 | else | 1500 | else |
| 1425 | BUG(); | 1501 | BUG(); |
| 1502 | return 0; | ||
| 1426 | } | 1503 | } |
| 1427 | 1504 | ||
| 1428 | static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, | 1505 | static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, |
| @@ -1431,7 +1508,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, | |||
| 1431 | enum omap_color_mode color_mode, bool fieldmode, | 1508 | enum omap_color_mode color_mode, bool fieldmode, |
| 1432 | unsigned int field_offset, | 1509 | unsigned int field_offset, |
| 1433 | unsigned *offset0, unsigned *offset1, | 1510 | unsigned *offset0, unsigned *offset1, |
| 1434 | s32 *row_inc, s32 *pix_inc) | 1511 | s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) |
| 1435 | { | 1512 | { |
| 1436 | u8 ps; | 1513 | u8 ps; |
| 1437 | 1514 | ||
| @@ -1477,10 +1554,10 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, | |||
| 1477 | else | 1554 | else |
| 1478 | *offset0 = 0; | 1555 | *offset0 = 0; |
| 1479 | 1556 | ||
| 1480 | *row_inc = pixinc(1 + (screen_width - width) + | 1557 | *row_inc = pixinc(1 + |
| 1481 | (fieldmode ? screen_width : 0), | 1558 | (y_predecim * screen_width - x_predecim * width) + |
| 1482 | ps); | 1559 | (fieldmode ? screen_width : 0), ps); |
| 1483 | *pix_inc = pixinc(1, ps); | 1560 | *pix_inc = pixinc(x_predecim, ps); |
| 1484 | break; | 1561 | break; |
| 1485 | 1562 | ||
| 1486 | case OMAP_DSS_ROT_0 + 4: | 1563 | case OMAP_DSS_ROT_0 + 4: |
| @@ -1498,14 +1575,15 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, | |||
| 1498 | *offset0 = field_offset * screen_width * ps; | 1575 | *offset0 = field_offset * screen_width * ps; |
| 1499 | else | 1576 | else |
| 1500 | *offset0 = 0; | 1577 | *offset0 = 0; |
| 1501 | *row_inc = pixinc(1 - (screen_width + width) - | 1578 | *row_inc = pixinc(1 - |
| 1502 | (fieldmode ? screen_width : 0), | 1579 | (y_predecim * screen_width + x_predecim * width) - |
| 1503 | ps); | 1580 | (fieldmode ? screen_width : 0), ps); |
| 1504 | *pix_inc = pixinc(1, ps); | 1581 | *pix_inc = pixinc(x_predecim, ps); |
| 1505 | break; | 1582 | break; |
| 1506 | 1583 | ||
| 1507 | default: | 1584 | default: |
| 1508 | BUG(); | 1585 | BUG(); |
| 1586 | return; | ||
| 1509 | } | 1587 | } |
| 1510 | } | 1588 | } |
| 1511 | 1589 | ||
| @@ -1515,7 +1593,7 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
| 1515 | enum omap_color_mode color_mode, bool fieldmode, | 1593 | enum omap_color_mode color_mode, bool fieldmode, |
| 1516 | unsigned int field_offset, | 1594 | unsigned int field_offset, |
| 1517 | unsigned *offset0, unsigned *offset1, | 1595 | unsigned *offset0, unsigned *offset1, |
| 1518 | s32 *row_inc, s32 *pix_inc) | 1596 | s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) |
| 1519 | { | 1597 | { |
| 1520 | u8 ps; | 1598 | u8 ps; |
| 1521 | u16 fbw, fbh; | 1599 | u16 fbw, fbh; |
| @@ -1557,10 +1635,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
| 1557 | *offset0 = *offset1 + field_offset * screen_width * ps; | 1635 | *offset0 = *offset1 + field_offset * screen_width * ps; |
| 1558 | else | 1636 | else |
| 1559 | *offset0 = *offset1; | 1637 | *offset0 = *offset1; |
| 1560 | *row_inc = pixinc(1 + (screen_width - fbw) + | 1638 | *row_inc = pixinc(1 + |
| 1561 | (fieldmode ? screen_width : 0), | 1639 | (y_predecim * screen_width - fbw * x_predecim) + |
| 1562 | ps); | 1640 | (fieldmode ? screen_width : 0), ps); |
| 1563 | *pix_inc = pixinc(1, ps); | 1641 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
| 1642 | color_mode == OMAP_DSS_COLOR_UYVY) | ||
| 1643 | *pix_inc = pixinc(x_predecim, 2 * ps); | ||
| 1644 | else | ||
| 1645 | *pix_inc = pixinc(x_predecim, ps); | ||
| 1564 | break; | 1646 | break; |
| 1565 | case OMAP_DSS_ROT_90: | 1647 | case OMAP_DSS_ROT_90: |
| 1566 | *offset1 = screen_width * (fbh - 1) * ps; | 1648 | *offset1 = screen_width * (fbh - 1) * ps; |
| @@ -1568,9 +1650,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
| 1568 | *offset0 = *offset1 + field_offset * ps; | 1650 | *offset0 = *offset1 + field_offset * ps; |
| 1569 | else | 1651 | else |
| 1570 | *offset0 = *offset1; | 1652 | *offset0 = *offset1; |
| 1571 | *row_inc = pixinc(screen_width * (fbh - 1) + 1 + | 1653 | *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) + |
| 1572 | (fieldmode ? 1 : 0), ps); | 1654 | y_predecim + (fieldmode ? 1 : 0), ps); |
| 1573 | *pix_inc = pixinc(-screen_width, ps); | 1655 | *pix_inc = pixinc(-x_predecim * screen_width, ps); |
| 1574 | break; | 1656 | break; |
| 1575 | case OMAP_DSS_ROT_180: | 1657 | case OMAP_DSS_ROT_180: |
| 1576 | *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; | 1658 | *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; |
| @@ -1579,10 +1661,13 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
| 1579 | else | 1661 | else |
| 1580 | *offset0 = *offset1; | 1662 | *offset0 = *offset1; |
| 1581 | *row_inc = pixinc(-1 - | 1663 | *row_inc = pixinc(-1 - |
| 1582 | (screen_width - fbw) - | 1664 | (y_predecim * screen_width - fbw * x_predecim) - |
| 1583 | (fieldmode ? screen_width : 0), | 1665 | (fieldmode ? screen_width : 0), ps); |
| 1584 | ps); | 1666 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
| 1585 | *pix_inc = pixinc(-1, ps); | 1667 | color_mode == OMAP_DSS_COLOR_UYVY) |
| 1668 | *pix_inc = pixinc(-x_predecim, 2 * ps); | ||
| 1669 | else | ||
| 1670 | *pix_inc = pixinc(-x_predecim, ps); | ||
| 1586 | break; | 1671 | break; |
| 1587 | case OMAP_DSS_ROT_270: | 1672 | case OMAP_DSS_ROT_270: |
| 1588 | *offset1 = (fbw - 1) * ps; | 1673 | *offset1 = (fbw - 1) * ps; |
| @@ -1590,9 +1675,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
| 1590 | *offset0 = *offset1 - field_offset * ps; | 1675 | *offset0 = *offset1 - field_offset * ps; |
| 1591 | else | 1676 | else |
| 1592 | *offset0 = *offset1; | 1677 | *offset0 = *offset1; |
| 1593 | *row_inc = pixinc(-screen_width * (fbh - 1) - 1 - | 1678 | *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) - |
| 1594 | (fieldmode ? 1 : 0), ps); | 1679 | y_predecim - (fieldmode ? 1 : 0), ps); |
| 1595 | *pix_inc = pixinc(screen_width, ps); | 1680 | *pix_inc = pixinc(x_predecim * screen_width, ps); |
| 1596 | break; | 1681 | break; |
| 1597 | 1682 | ||
| 1598 | /* mirroring */ | 1683 | /* mirroring */ |
| @@ -1602,10 +1687,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
| 1602 | *offset0 = *offset1 + field_offset * screen_width * ps; | 1687 | *offset0 = *offset1 + field_offset * screen_width * ps; |
| 1603 | else | 1688 | else |
| 1604 | *offset0 = *offset1; | 1689 | *offset0 = *offset1; |
| 1605 | *row_inc = pixinc(screen_width * 2 - 1 + | 1690 | *row_inc = pixinc(y_predecim * screen_width * 2 - 1 + |
| 1606 | (fieldmode ? screen_width : 0), | 1691 | (fieldmode ? screen_width : 0), |
| 1607 | ps); | 1692 | ps); |
| 1608 | *pix_inc = pixinc(-1, ps); | 1693 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
| 1694 | color_mode == OMAP_DSS_COLOR_UYVY) | ||
| 1695 | *pix_inc = pixinc(-x_predecim, 2 * ps); | ||
| 1696 | else | ||
| 1697 | *pix_inc = pixinc(-x_predecim, ps); | ||
| 1609 | break; | 1698 | break; |
| 1610 | 1699 | ||
| 1611 | case OMAP_DSS_ROT_90 + 4: | 1700 | case OMAP_DSS_ROT_90 + 4: |
| @@ -1614,10 +1703,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
| 1614 | *offset0 = *offset1 + field_offset * ps; | 1703 | *offset0 = *offset1 + field_offset * ps; |
| 1615 | else | 1704 | else |
| 1616 | *offset0 = *offset1; | 1705 | *offset0 = *offset1; |
| 1617 | *row_inc = pixinc(-screen_width * (fbh - 1) + 1 + | 1706 | *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) + |
| 1618 | (fieldmode ? 1 : 0), | 1707 | y_predecim + (fieldmode ? 1 : 0), |
| 1619 | ps); | 1708 | ps); |
| 1620 | *pix_inc = pixinc(screen_width, ps); | 1709 | *pix_inc = pixinc(x_predecim * screen_width, ps); |
| 1621 | break; | 1710 | break; |
| 1622 | 1711 | ||
| 1623 | case OMAP_DSS_ROT_180 + 4: | 1712 | case OMAP_DSS_ROT_180 + 4: |
| @@ -1626,10 +1715,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
| 1626 | *offset0 = *offset1 - field_offset * screen_width * ps; | 1715 | *offset0 = *offset1 - field_offset * screen_width * ps; |
| 1627 | else | 1716 | else |
| 1628 | *offset0 = *offset1; | 1717 | *offset0 = *offset1; |
| 1629 | *row_inc = pixinc(1 - screen_width * 2 - | 1718 | *row_inc = pixinc(1 - y_predecim * screen_width * 2 - |
| 1630 | (fieldmode ? screen_width : 0), | 1719 | (fieldmode ? screen_width : 0), |
| 1631 | ps); | 1720 | ps); |
| 1632 | *pix_inc = pixinc(1, ps); | 1721 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
| 1722 | color_mode == OMAP_DSS_COLOR_UYVY) | ||
| 1723 | *pix_inc = pixinc(x_predecim, 2 * ps); | ||
| 1724 | else | ||
| 1725 | *pix_inc = pixinc(x_predecim, ps); | ||
| 1633 | break; | 1726 | break; |
| 1634 | 1727 | ||
| 1635 | case OMAP_DSS_ROT_270 + 4: | 1728 | case OMAP_DSS_ROT_270 + 4: |
| @@ -1638,34 +1731,130 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
| 1638 | *offset0 = *offset1 - field_offset * ps; | 1731 | *offset0 = *offset1 - field_offset * ps; |
| 1639 | else | 1732 | else |
| 1640 | *offset0 = *offset1; | 1733 | *offset0 = *offset1; |
| 1641 | *row_inc = pixinc(screen_width * (fbh - 1) - 1 - | 1734 | *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) - |
| 1642 | (fieldmode ? 1 : 0), | 1735 | y_predecim - (fieldmode ? 1 : 0), |
| 1643 | ps); | 1736 | ps); |
| 1644 | *pix_inc = pixinc(-screen_width, ps); | 1737 | *pix_inc = pixinc(-x_predecim * screen_width, ps); |
| 1645 | break; | 1738 | break; |
| 1646 | 1739 | ||
| 1647 | default: | 1740 | default: |
| 1648 | BUG(); | 1741 | BUG(); |
| 1742 | return; | ||
| 1743 | } | ||
| 1744 | } | ||
| 1745 | |||
| 1746 | static void calc_tiler_rotation_offset(u16 screen_width, u16 width, | ||
| 1747 | enum omap_color_mode color_mode, bool fieldmode, | ||
| 1748 | unsigned int field_offset, unsigned *offset0, unsigned *offset1, | ||
| 1749 | s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) | ||
| 1750 | { | ||
| 1751 | u8 ps; | ||
| 1752 | |||
| 1753 | switch (color_mode) { | ||
| 1754 | case OMAP_DSS_COLOR_CLUT1: | ||
| 1755 | case OMAP_DSS_COLOR_CLUT2: | ||
| 1756 | case OMAP_DSS_COLOR_CLUT4: | ||
| 1757 | case OMAP_DSS_COLOR_CLUT8: | ||
| 1758 | BUG(); | ||
| 1759 | return; | ||
| 1760 | default: | ||
| 1761 | ps = color_mode_to_bpp(color_mode) / 8; | ||
| 1762 | break; | ||
| 1649 | } | 1763 | } |
| 1764 | |||
| 1765 | DSSDBG("scrw %d, width %d\n", screen_width, width); | ||
| 1766 | |||
| 1767 | /* | ||
| 1768 | * field 0 = even field = bottom field | ||
| 1769 | * field 1 = odd field = top field | ||
| 1770 | */ | ||
| 1771 | *offset1 = 0; | ||
| 1772 | if (field_offset) | ||
| 1773 | *offset0 = *offset1 + field_offset * screen_width * ps; | ||
| 1774 | else | ||
| 1775 | *offset0 = *offset1; | ||
| 1776 | *row_inc = pixinc(1 + (y_predecim * screen_width - width * x_predecim) + | ||
| 1777 | (fieldmode ? screen_width : 0), ps); | ||
| 1778 | if (color_mode == OMAP_DSS_COLOR_YUV2 || | ||
| 1779 | color_mode == OMAP_DSS_COLOR_UYVY) | ||
| 1780 | *pix_inc = pixinc(x_predecim, 2 * ps); | ||
| 1781 | else | ||
| 1782 | *pix_inc = pixinc(x_predecim, ps); | ||
| 1650 | } | 1783 | } |
| 1651 | 1784 | ||
| 1652 | static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, | 1785 | /* |
| 1786 | * This function is used to avoid synclosts in OMAP3, because of some | ||
| 1787 | * undocumented horizontal position and timing related limitations. | ||
| 1788 | */ | ||
| 1789 | static int check_horiz_timing_omap3(enum omap_channel channel, | ||
| 1790 | const struct omap_video_timings *t, u16 pos_x, | ||
| 1791 | u16 width, u16 height, u16 out_width, u16 out_height) | ||
| 1792 | { | ||
| 1793 | int DS = DIV_ROUND_UP(height, out_height); | ||
| 1794 | unsigned long nonactive, lclk, pclk; | ||
| 1795 | static const u8 limits[3] = { 8, 10, 20 }; | ||
| 1796 | u64 val, blank; | ||
| 1797 | int i; | ||
| 1798 | |||
| 1799 | nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; | ||
| 1800 | pclk = dispc_mgr_pclk_rate(channel); | ||
| 1801 | if (dispc_mgr_is_lcd(channel)) | ||
| 1802 | lclk = dispc_mgr_lclk_rate(channel); | ||
| 1803 | else | ||
| 1804 | lclk = dispc_fclk_rate(); | ||
| 1805 | |||
| 1806 | i = 0; | ||
| 1807 | if (out_height < height) | ||
| 1808 | i++; | ||
| 1809 | if (out_width < width) | ||
| 1810 | i++; | ||
| 1811 | blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk); | ||
| 1812 | DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]); | ||
| 1813 | if (blank <= limits[i]) | ||
| 1814 | return -EINVAL; | ||
| 1815 | |||
| 1816 | /* | ||
| 1817 | * Pixel data should be prepared before visible display point starts. | ||
| 1818 | * So, atleast DS-2 lines must have already been fetched by DISPC | ||
| 1819 | * during nonactive - pos_x period. | ||
| 1820 | */ | ||
| 1821 | val = div_u64((u64)(nonactive - pos_x) * lclk, pclk); | ||
| 1822 | DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n", | ||
| 1823 | val, max(0, DS - 2) * width); | ||
| 1824 | if (val < max(0, DS - 2) * width) | ||
| 1825 | return -EINVAL; | ||
| 1826 | |||
| 1827 | /* | ||
| 1828 | * All lines need to be refilled during the nonactive period of which | ||
| 1829 | * only one line can be loaded during the active period. So, atleast | ||
| 1830 | * DS - 1 lines should be loaded during nonactive period. | ||
| 1831 | */ | ||
| 1832 | val = div_u64((u64)nonactive * lclk, pclk); | ||
| 1833 | DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n", | ||
| 1834 | val, max(0, DS - 1) * width); | ||
| 1835 | if (val < max(0, DS - 1) * width) | ||
| 1836 | return -EINVAL; | ||
| 1837 | |||
| 1838 | return 0; | ||
| 1839 | } | ||
| 1840 | |||
| 1841 | static unsigned long calc_core_clk_five_taps(enum omap_channel channel, | ||
| 1842 | const struct omap_video_timings *mgr_timings, u16 width, | ||
| 1653 | u16 height, u16 out_width, u16 out_height, | 1843 | u16 height, u16 out_width, u16 out_height, |
| 1654 | enum omap_color_mode color_mode) | 1844 | enum omap_color_mode color_mode) |
| 1655 | { | 1845 | { |
| 1656 | u32 fclk = 0; | 1846 | u32 core_clk = 0; |
| 1657 | u64 tmp, pclk = dispc_mgr_pclk_rate(channel); | 1847 | u64 tmp, pclk = dispc_mgr_pclk_rate(channel); |
| 1658 | 1848 | ||
| 1659 | if (height <= out_height && width <= out_width) | 1849 | if (height <= out_height && width <= out_width) |
| 1660 | return (unsigned long) pclk; | 1850 | return (unsigned long) pclk; |
| 1661 | 1851 | ||
| 1662 | if (height > out_height) { | 1852 | if (height > out_height) { |
| 1663 | struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); | 1853 | unsigned int ppl = mgr_timings->x_res; |
| 1664 | unsigned int ppl = dssdev->panel.timings.x_res; | ||
| 1665 | 1854 | ||
| 1666 | tmp = pclk * height * out_width; | 1855 | tmp = pclk * height * out_width; |
| 1667 | do_div(tmp, 2 * out_height * ppl); | 1856 | do_div(tmp, 2 * out_height * ppl); |
| 1668 | fclk = tmp; | 1857 | core_clk = tmp; |
| 1669 | 1858 | ||
| 1670 | if (height > 2 * out_height) { | 1859 | if (height > 2 * out_height) { |
| 1671 | if (ppl == out_width) | 1860 | if (ppl == out_width) |
| @@ -1673,23 +1862,23 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, | |||
| 1673 | 1862 | ||
| 1674 | tmp = pclk * (height - 2 * out_height) * out_width; | 1863 | tmp = pclk * (height - 2 * out_height) * out_width; |
| 1675 | do_div(tmp, 2 * out_height * (ppl - out_width)); | 1864 | do_div(tmp, 2 * out_height * (ppl - out_width)); |
| 1676 | fclk = max(fclk, (u32) tmp); | 1865 | core_clk = max_t(u32, core_clk, tmp); |
| 1677 | } | 1866 | } |
| 1678 | } | 1867 | } |
| 1679 | 1868 | ||
| 1680 | if (width > out_width) { | 1869 | if (width > out_width) { |
| 1681 | tmp = pclk * width; | 1870 | tmp = pclk * width; |
| 1682 | do_div(tmp, out_width); | 1871 | do_div(tmp, out_width); |
| 1683 | fclk = max(fclk, (u32) tmp); | 1872 | core_clk = max_t(u32, core_clk, tmp); |
| 1684 | 1873 | ||
| 1685 | if (color_mode == OMAP_DSS_COLOR_RGB24U) | 1874 | if (color_mode == OMAP_DSS_COLOR_RGB24U) |
| 1686 | fclk <<= 1; | 1875 | core_clk <<= 1; |
| 1687 | } | 1876 | } |
| 1688 | 1877 | ||
| 1689 | return fclk; | 1878 | return core_clk; |
| 1690 | } | 1879 | } |
| 1691 | 1880 | ||
| 1692 | static unsigned long calc_fclk(enum omap_channel channel, u16 width, | 1881 | static unsigned long calc_core_clk(enum omap_channel channel, u16 width, |
| 1693 | u16 height, u16 out_width, u16 out_height) | 1882 | u16 height, u16 out_width, u16 out_height) |
| 1694 | { | 1883 | { |
| 1695 | unsigned int hf, vf; | 1884 | unsigned int hf, vf; |
| @@ -1730,15 +1919,20 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, | |||
| 1730 | } | 1919 | } |
| 1731 | 1920 | ||
| 1732 | static int dispc_ovl_calc_scaling(enum omap_plane plane, | 1921 | static int dispc_ovl_calc_scaling(enum omap_plane plane, |
| 1733 | enum omap_channel channel, u16 width, u16 height, | 1922 | enum omap_channel channel, |
| 1734 | u16 out_width, u16 out_height, | 1923 | const struct omap_video_timings *mgr_timings, |
| 1735 | enum omap_color_mode color_mode, bool *five_taps) | 1924 | u16 width, u16 height, u16 out_width, u16 out_height, |
| 1925 | enum omap_color_mode color_mode, bool *five_taps, | ||
| 1926 | int *x_predecim, int *y_predecim, u16 pos_x) | ||
| 1736 | { | 1927 | { |
| 1737 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); | 1928 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
| 1738 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); | 1929 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); |
| 1739 | const int maxsinglelinewidth = | 1930 | const int maxsinglelinewidth = |
| 1740 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); | 1931 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); |
| 1741 | unsigned long fclk = 0; | 1932 | const int max_decim_limit = 16; |
| 1933 | unsigned long core_clk = 0; | ||
| 1934 | int decim_x, decim_y, error, min_factor; | ||
| 1935 | u16 in_width, in_height, in_width_max = 0; | ||
| 1742 | 1936 | ||
| 1743 | if (width == out_width && height == out_height) | 1937 | if (width == out_width && height == out_height) |
| 1744 | return 0; | 1938 | return 0; |
| @@ -1746,64 +1940,154 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, | |||
| 1746 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) | 1940 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) |
| 1747 | return -EINVAL; | 1941 | return -EINVAL; |
| 1748 | 1942 | ||
| 1749 | if (out_width < width / maxdownscale || | 1943 | *x_predecim = max_decim_limit; |
| 1750 | out_width > width * 8) | 1944 | *y_predecim = max_decim_limit; |
| 1945 | |||
| 1946 | if (color_mode == OMAP_DSS_COLOR_CLUT1 || | ||
| 1947 | color_mode == OMAP_DSS_COLOR_CLUT2 || | ||
| 1948 | color_mode == OMAP_DSS_COLOR_CLUT4 || | ||
| 1949 | color_mode == OMAP_DSS_COLOR_CLUT8) { | ||
| 1950 | *x_predecim = 1; | ||
| 1951 | *y_predecim = 1; | ||
| 1952 | *five_taps = false; | ||
| 1953 | return 0; | ||
| 1954 | } | ||
| 1955 | |||
| 1956 | decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale); | ||
| 1957 | decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); | ||
| 1958 | |||
| 1959 | min_factor = min(decim_x, decim_y); | ||
| 1960 | |||
| 1961 | if (decim_x > *x_predecim || out_width > width * 8) | ||
| 1751 | return -EINVAL; | 1962 | return -EINVAL; |
| 1752 | 1963 | ||
| 1753 | if (out_height < height / maxdownscale || | 1964 | if (decim_y > *y_predecim || out_height > height * 8) |
| 1754 | out_height > height * 8) | ||
| 1755 | return -EINVAL; | 1965 | return -EINVAL; |
| 1756 | 1966 | ||
| 1757 | if (cpu_is_omap24xx()) { | 1967 | if (cpu_is_omap24xx()) { |
| 1758 | if (width > maxsinglelinewidth) | ||
| 1759 | DSSERR("Cannot scale max input width exceeded"); | ||
| 1760 | *five_taps = false; | 1968 | *five_taps = false; |
| 1761 | fclk = calc_fclk(channel, width, height, out_width, | 1969 | |
| 1762 | out_height); | 1970 | do { |
| 1971 | in_height = DIV_ROUND_UP(height, decim_y); | ||
| 1972 | in_width = DIV_ROUND_UP(width, decim_x); | ||
| 1973 | core_clk = calc_core_clk(channel, in_width, in_height, | ||
| 1974 | out_width, out_height); | ||
| 1975 | error = (in_width > maxsinglelinewidth || !core_clk || | ||
| 1976 | core_clk > dispc_core_clk_rate()); | ||
| 1977 | if (error) { | ||
| 1978 | if (decim_x == decim_y) { | ||
| 1979 | decim_x = min_factor; | ||
| 1980 | decim_y++; | ||
| 1981 | } else { | ||
| 1982 | swap(decim_x, decim_y); | ||
| 1983 | if (decim_x < decim_y) | ||
| 1984 | decim_x++; | ||
| 1985 | } | ||
| 1986 | } | ||
| 1987 | } while (decim_x <= *x_predecim && decim_y <= *y_predecim && | ||
| 1988 | error); | ||
| 1989 | |||
| 1990 | if (in_width > maxsinglelinewidth) { | ||
| 1991 | DSSERR("Cannot scale max input width exceeded"); | ||
| 1992 | return -EINVAL; | ||
| 1993 | } | ||
| 1763 | } else if (cpu_is_omap34xx()) { | 1994 | } else if (cpu_is_omap34xx()) { |
| 1764 | if (width > (maxsinglelinewidth * 2)) { | 1995 | |
| 1996 | do { | ||
| 1997 | in_height = DIV_ROUND_UP(height, decim_y); | ||
| 1998 | in_width = DIV_ROUND_UP(width, decim_x); | ||
| 1999 | core_clk = calc_core_clk_five_taps(channel, mgr_timings, | ||
| 2000 | in_width, in_height, out_width, out_height, | ||
| 2001 | color_mode); | ||
| 2002 | |||
| 2003 | error = check_horiz_timing_omap3(channel, mgr_timings, | ||
| 2004 | pos_x, in_width, in_height, out_width, | ||
| 2005 | out_height); | ||
| 2006 | |||
| 2007 | if (in_width > maxsinglelinewidth) | ||
| 2008 | if (in_height > out_height && | ||
| 2009 | in_height < out_height * 2) | ||
| 2010 | *five_taps = false; | ||
| 2011 | if (!*five_taps) | ||
| 2012 | core_clk = calc_core_clk(channel, in_width, | ||
| 2013 | in_height, out_width, out_height); | ||
| 2014 | error = (error || in_width > maxsinglelinewidth * 2 || | ||
| 2015 | (in_width > maxsinglelinewidth && *five_taps) || | ||
| 2016 | !core_clk || core_clk > dispc_core_clk_rate()); | ||
| 2017 | if (error) { | ||
| 2018 | if (decim_x == decim_y) { | ||
| 2019 | decim_x = min_factor; | ||
| 2020 | decim_y++; | ||
| 2021 | } else { | ||
| 2022 | swap(decim_x, decim_y); | ||
| 2023 | if (decim_x < decim_y) | ||
| 2024 | decim_x++; | ||
| 2025 | } | ||
| 2026 | } | ||
| 2027 | } while (decim_x <= *x_predecim && decim_y <= *y_predecim | ||
| 2028 | && error); | ||
| 2029 | |||
| 2030 | if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, | ||
| 2031 | height, out_width, out_height)){ | ||
| 2032 | DSSERR("horizontal timing too tight\n"); | ||
| 2033 | return -EINVAL; | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | if (in_width > (maxsinglelinewidth * 2)) { | ||
| 1765 | DSSERR("Cannot setup scaling"); | 2037 | DSSERR("Cannot setup scaling"); |
| 1766 | DSSERR("width exceeds maximum width possible"); | 2038 | DSSERR("width exceeds maximum width possible"); |
| 1767 | return -EINVAL; | 2039 | return -EINVAL; |
| 1768 | } | 2040 | } |
| 1769 | fclk = calc_fclk_five_taps(channel, width, height, out_width, | 2041 | |
| 1770 | out_height, color_mode); | 2042 | if (in_width > maxsinglelinewidth && *five_taps) { |
| 1771 | if (width > maxsinglelinewidth) { | 2043 | DSSERR("cannot setup scaling with five taps"); |
| 1772 | if (height > out_height && height < out_height * 2) | 2044 | return -EINVAL; |
| 1773 | *five_taps = false; | ||
| 1774 | else { | ||
| 1775 | DSSERR("cannot setup scaling with five taps"); | ||
| 1776 | return -EINVAL; | ||
| 1777 | } | ||
| 1778 | } | 2045 | } |
| 1779 | if (!*five_taps) | ||
| 1780 | fclk = calc_fclk(channel, width, height, out_width, | ||
| 1781 | out_height); | ||
| 1782 | } else { | 2046 | } else { |
| 1783 | if (width > maxsinglelinewidth) { | 2047 | int decim_x_min = decim_x; |
| 2048 | in_height = DIV_ROUND_UP(height, decim_y); | ||
| 2049 | in_width_max = dispc_core_clk_rate() / | ||
| 2050 | DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), | ||
| 2051 | out_width); | ||
| 2052 | decim_x = DIV_ROUND_UP(width, in_width_max); | ||
| 2053 | |||
| 2054 | decim_x = decim_x > decim_x_min ? decim_x : decim_x_min; | ||
| 2055 | if (decim_x > *x_predecim) | ||
| 2056 | return -EINVAL; | ||
| 2057 | |||
| 2058 | do { | ||
| 2059 | in_width = DIV_ROUND_UP(width, decim_x); | ||
| 2060 | } while (decim_x <= *x_predecim && | ||
| 2061 | in_width > maxsinglelinewidth && decim_x++); | ||
| 2062 | |||
| 2063 | if (in_width > maxsinglelinewidth) { | ||
| 1784 | DSSERR("Cannot scale width exceeds max line width"); | 2064 | DSSERR("Cannot scale width exceeds max line width"); |
| 1785 | return -EINVAL; | 2065 | return -EINVAL; |
| 1786 | } | 2066 | } |
| 1787 | fclk = calc_fclk(channel, width, height, out_width, | 2067 | |
| 1788 | out_height); | 2068 | core_clk = calc_core_clk(channel, in_width, in_height, |
| 2069 | out_width, out_height); | ||
| 1789 | } | 2070 | } |
| 1790 | 2071 | ||
| 1791 | DSSDBG("required fclk rate = %lu Hz\n", fclk); | 2072 | DSSDBG("required core clk rate = %lu Hz\n", core_clk); |
| 1792 | DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); | 2073 | DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); |
| 1793 | 2074 | ||
| 1794 | if (!fclk || fclk > dispc_fclk_rate()) { | 2075 | if (!core_clk || core_clk > dispc_core_clk_rate()) { |
| 1795 | DSSERR("failed to set up scaling, " | 2076 | DSSERR("failed to set up scaling, " |
| 1796 | "required fclk rate = %lu Hz, " | 2077 | "required core clk rate = %lu Hz, " |
| 1797 | "current fclk rate = %lu Hz\n", | 2078 | "current core clk rate = %lu Hz\n", |
| 1798 | fclk, dispc_fclk_rate()); | 2079 | core_clk, dispc_core_clk_rate()); |
| 1799 | return -EINVAL; | 2080 | return -EINVAL; |
| 1800 | } | 2081 | } |
| 1801 | 2082 | ||
| 2083 | *x_predecim = decim_x; | ||
| 2084 | *y_predecim = decim_y; | ||
| 1802 | return 0; | 2085 | return 0; |
| 1803 | } | 2086 | } |
| 1804 | 2087 | ||
| 1805 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | 2088 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, |
| 1806 | bool ilace, bool replication) | 2089 | bool ilace, bool replication, |
| 2090 | const struct omap_video_timings *mgr_timings) | ||
| 1807 | { | 2091 | { |
| 1808 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); | 2092 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
| 1809 | bool five_taps = true; | 2093 | bool five_taps = true; |
| @@ -1814,8 +2098,11 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | |||
| 1814 | s32 pix_inc; | 2098 | s32 pix_inc; |
| 1815 | u16 frame_height = oi->height; | 2099 | u16 frame_height = oi->height; |
| 1816 | unsigned int field_offset = 0; | 2100 | unsigned int field_offset = 0; |
| 1817 | u16 outw, outh; | 2101 | u16 in_height = oi->height; |
| 2102 | u16 in_width = oi->width; | ||
| 2103 | u16 out_width, out_height; | ||
| 1818 | enum omap_channel channel; | 2104 | enum omap_channel channel; |
| 2105 | int x_predecim = 1, y_predecim = 1; | ||
| 1819 | 2106 | ||
| 1820 | channel = dispc_ovl_get_channel_out(plane); | 2107 | channel = dispc_ovl_get_channel_out(plane); |
| 1821 | 2108 | ||
| @@ -1829,32 +2116,35 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | |||
| 1829 | if (oi->paddr == 0) | 2116 | if (oi->paddr == 0) |
| 1830 | return -EINVAL; | 2117 | return -EINVAL; |
| 1831 | 2118 | ||
| 1832 | outw = oi->out_width == 0 ? oi->width : oi->out_width; | 2119 | out_width = oi->out_width == 0 ? oi->width : oi->out_width; |
| 1833 | outh = oi->out_height == 0 ? oi->height : oi->out_height; | 2120 | out_height = oi->out_height == 0 ? oi->height : oi->out_height; |
| 1834 | 2121 | ||
| 1835 | if (ilace && oi->height == outh) | 2122 | if (ilace && oi->height == out_height) |
| 1836 | fieldmode = 1; | 2123 | fieldmode = 1; |
| 1837 | 2124 | ||
| 1838 | if (ilace) { | 2125 | if (ilace) { |
| 1839 | if (fieldmode) | 2126 | if (fieldmode) |
| 1840 | oi->height /= 2; | 2127 | in_height /= 2; |
| 1841 | oi->pos_y /= 2; | 2128 | oi->pos_y /= 2; |
| 1842 | outh /= 2; | 2129 | out_height /= 2; |
| 1843 | 2130 | ||
| 1844 | DSSDBG("adjusting for ilace: height %d, pos_y %d, " | 2131 | DSSDBG("adjusting for ilace: height %d, pos_y %d, " |
| 1845 | "out_height %d\n", | 2132 | "out_height %d\n", |
| 1846 | oi->height, oi->pos_y, outh); | 2133 | in_height, oi->pos_y, out_height); |
| 1847 | } | 2134 | } |
| 1848 | 2135 | ||
| 1849 | if (!dss_feat_color_mode_supported(plane, oi->color_mode)) | 2136 | if (!dss_feat_color_mode_supported(plane, oi->color_mode)) |
| 1850 | return -EINVAL; | 2137 | return -EINVAL; |
| 1851 | 2138 | ||
| 1852 | r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, | 2139 | r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width, |
| 1853 | outw, outh, oi->color_mode, | 2140 | in_height, out_width, out_height, oi->color_mode, |
| 1854 | &five_taps); | 2141 | &five_taps, &x_predecim, &y_predecim, oi->pos_x); |
| 1855 | if (r) | 2142 | if (r) |
| 1856 | return r; | 2143 | return r; |
| 1857 | 2144 | ||
| 2145 | in_width = DIV_ROUND_UP(in_width, x_predecim); | ||
| 2146 | in_height = DIV_ROUND_UP(in_height, y_predecim); | ||
| 2147 | |||
| 1858 | if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || | 2148 | if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || |
| 1859 | oi->color_mode == OMAP_DSS_COLOR_UYVY || | 2149 | oi->color_mode == OMAP_DSS_COLOR_UYVY || |
| 1860 | oi->color_mode == OMAP_DSS_COLOR_NV12) | 2150 | oi->color_mode == OMAP_DSS_COLOR_NV12) |
| @@ -1868,32 +2158,46 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | |||
| 1868 | * so the integer part must be added to the base address of the | 2158 | * so the integer part must be added to the base address of the |
| 1869 | * bottom field. | 2159 | * bottom field. |
| 1870 | */ | 2160 | */ |
| 1871 | if (!oi->height || oi->height == outh) | 2161 | if (!in_height || in_height == out_height) |
| 1872 | field_offset = 0; | 2162 | field_offset = 0; |
| 1873 | else | 2163 | else |
| 1874 | field_offset = oi->height / outh / 2; | 2164 | field_offset = in_height / out_height / 2; |
| 1875 | } | 2165 | } |
| 1876 | 2166 | ||
| 1877 | /* Fields are independent but interleaved in memory. */ | 2167 | /* Fields are independent but interleaved in memory. */ |
| 1878 | if (fieldmode) | 2168 | if (fieldmode) |
| 1879 | field_offset = 1; | 2169 | field_offset = 1; |
| 1880 | 2170 | ||
| 1881 | if (oi->rotation_type == OMAP_DSS_ROT_DMA) | 2171 | offset0 = 0; |
| 2172 | offset1 = 0; | ||
| 2173 | row_inc = 0; | ||
| 2174 | pix_inc = 0; | ||
| 2175 | |||
| 2176 | if (oi->rotation_type == OMAP_DSS_ROT_TILER) | ||
| 2177 | calc_tiler_rotation_offset(oi->screen_width, in_width, | ||
| 2178 | oi->color_mode, fieldmode, field_offset, | ||
| 2179 | &offset0, &offset1, &row_inc, &pix_inc, | ||
| 2180 | x_predecim, y_predecim); | ||
| 2181 | else if (oi->rotation_type == OMAP_DSS_ROT_DMA) | ||
| 1882 | calc_dma_rotation_offset(oi->rotation, oi->mirror, | 2182 | calc_dma_rotation_offset(oi->rotation, oi->mirror, |
| 1883 | oi->screen_width, oi->width, frame_height, | 2183 | oi->screen_width, in_width, frame_height, |
| 1884 | oi->color_mode, fieldmode, field_offset, | 2184 | oi->color_mode, fieldmode, field_offset, |
| 1885 | &offset0, &offset1, &row_inc, &pix_inc); | 2185 | &offset0, &offset1, &row_inc, &pix_inc, |
| 2186 | x_predecim, y_predecim); | ||
| 1886 | else | 2187 | else |
| 1887 | calc_vrfb_rotation_offset(oi->rotation, oi->mirror, | 2188 | calc_vrfb_rotation_offset(oi->rotation, oi->mirror, |
| 1888 | oi->screen_width, oi->width, frame_height, | 2189 | oi->screen_width, in_width, frame_height, |
| 1889 | oi->color_mode, fieldmode, field_offset, | 2190 | oi->color_mode, fieldmode, field_offset, |
| 1890 | &offset0, &offset1, &row_inc, &pix_inc); | 2191 | &offset0, &offset1, &row_inc, &pix_inc, |
| 2192 | x_predecim, y_predecim); | ||
| 1891 | 2193 | ||
| 1892 | DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", | 2194 | DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", |
| 1893 | offset0, offset1, row_inc, pix_inc); | 2195 | offset0, offset1, row_inc, pix_inc); |
| 1894 | 2196 | ||
| 1895 | dispc_ovl_set_color_mode(plane, oi->color_mode); | 2197 | dispc_ovl_set_color_mode(plane, oi->color_mode); |
| 1896 | 2198 | ||
| 2199 | dispc_ovl_configure_burst_type(plane, oi->rotation_type); | ||
| 2200 | |||
| 1897 | dispc_ovl_set_ba0(plane, oi->paddr + offset0); | 2201 | dispc_ovl_set_ba0(plane, oi->paddr + offset0); |
| 1898 | dispc_ovl_set_ba1(plane, oi->paddr + offset1); | 2202 | dispc_ovl_set_ba1(plane, oi->paddr + offset1); |
| 1899 | 2203 | ||
| @@ -1906,19 +2210,18 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | |||
| 1906 | dispc_ovl_set_row_inc(plane, row_inc); | 2210 | dispc_ovl_set_row_inc(plane, row_inc); |
| 1907 | dispc_ovl_set_pix_inc(plane, pix_inc); | 2211 | dispc_ovl_set_pix_inc(plane, pix_inc); |
| 1908 | 2212 | ||
| 1909 | DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width, | 2213 | DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width, |
| 1910 | oi->height, outw, outh); | 2214 | in_height, out_width, out_height); |
| 1911 | 2215 | ||
| 1912 | dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); | 2216 | dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); |
| 1913 | 2217 | ||
| 1914 | dispc_ovl_set_pic_size(plane, oi->width, oi->height); | 2218 | dispc_ovl_set_pic_size(plane, in_width, in_height); |
| 1915 | 2219 | ||
| 1916 | if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { | 2220 | if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { |
| 1917 | dispc_ovl_set_scaling(plane, oi->width, oi->height, | 2221 | dispc_ovl_set_scaling(plane, in_width, in_height, out_width, |
| 1918 | outw, outh, | 2222 | out_height, ilace, five_taps, fieldmode, |
| 1919 | ilace, five_taps, fieldmode, | ||
| 1920 | oi->color_mode, oi->rotation); | 2223 | oi->color_mode, oi->rotation); |
| 1921 | dispc_ovl_set_vid_size(plane, outw, outh); | 2224 | dispc_ovl_set_vid_size(plane, out_width, out_height); |
| 1922 | dispc_ovl_set_vid_color_conv(plane, cconv); | 2225 | dispc_ovl_set_vid_color_conv(plane, cconv); |
| 1923 | } | 2226 | } |
| 1924 | 2227 | ||
| @@ -2087,8 +2390,10 @@ bool dispc_mgr_is_enabled(enum omap_channel channel) | |||
| 2087 | return !!REG_GET(DISPC_CONTROL, 1, 1); | 2390 | return !!REG_GET(DISPC_CONTROL, 1, 1); |
| 2088 | else if (channel == OMAP_DSS_CHANNEL_LCD2) | 2391 | else if (channel == OMAP_DSS_CHANNEL_LCD2) |
| 2089 | return !!REG_GET(DISPC_CONTROL2, 0, 0); | 2392 | return !!REG_GET(DISPC_CONTROL2, 0, 0); |
| 2090 | else | 2393 | else { |
| 2091 | BUG(); | 2394 | BUG(); |
| 2395 | return false; | ||
| 2396 | } | ||
| 2092 | } | 2397 | } |
| 2093 | 2398 | ||
| 2094 | void dispc_mgr_enable(enum omap_channel channel, bool enable) | 2399 | void dispc_mgr_enable(enum omap_channel channel, bool enable) |
| @@ -2285,6 +2590,12 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) | |||
| 2285 | REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11); | 2590 | REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11); |
| 2286 | } | 2591 | } |
| 2287 | 2592 | ||
| 2593 | static bool _dispc_mgr_size_ok(u16 width, u16 height) | ||
| 2594 | { | ||
| 2595 | return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) && | ||
| 2596 | height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT); | ||
| 2597 | } | ||
| 2598 | |||
| 2288 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, | 2599 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, |
| 2289 | int vsw, int vfp, int vbp) | 2600 | int vsw, int vfp, int vbp) |
| 2290 | { | 2601 | { |
| @@ -2309,11 +2620,20 @@ static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, | |||
| 2309 | return true; | 2620 | return true; |
| 2310 | } | 2621 | } |
| 2311 | 2622 | ||
| 2312 | bool dispc_lcd_timings_ok(struct omap_video_timings *timings) | 2623 | bool dispc_mgr_timings_ok(enum omap_channel channel, |
| 2624 | const struct omap_video_timings *timings) | ||
| 2313 | { | 2625 | { |
| 2314 | return _dispc_lcd_timings_ok(timings->hsw, timings->hfp, | 2626 | bool timings_ok; |
| 2315 | timings->hbp, timings->vsw, | 2627 | |
| 2316 | timings->vfp, timings->vbp); | 2628 | timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res); |
| 2629 | |||
| 2630 | if (dispc_mgr_is_lcd(channel)) | ||
| 2631 | timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw, | ||
| 2632 | timings->hfp, timings->hbp, | ||
| 2633 | timings->vsw, timings->vfp, | ||
| 2634 | timings->vbp); | ||
| 2635 | |||
| 2636 | return timings_ok; | ||
| 2317 | } | 2637 | } |
| 2318 | 2638 | ||
| 2319 | static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, | 2639 | static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, |
| @@ -2340,37 +2660,45 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, | |||
| 2340 | } | 2660 | } |
| 2341 | 2661 | ||
| 2342 | /* change name to mode? */ | 2662 | /* change name to mode? */ |
| 2343 | void dispc_mgr_set_lcd_timings(enum omap_channel channel, | 2663 | void dispc_mgr_set_timings(enum omap_channel channel, |
| 2344 | struct omap_video_timings *timings) | 2664 | struct omap_video_timings *timings) |
| 2345 | { | 2665 | { |
| 2346 | unsigned xtot, ytot; | 2666 | unsigned xtot, ytot; |
| 2347 | unsigned long ht, vt; | 2667 | unsigned long ht, vt; |
| 2668 | struct omap_video_timings t = *timings; | ||
| 2669 | |||
| 2670 | DSSDBG("channel %d xres %u yres %u\n", channel, t.x_res, t.y_res); | ||
| 2348 | 2671 | ||
| 2349 | if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp, | 2672 | if (!dispc_mgr_timings_ok(channel, &t)) { |
| 2350 | timings->hbp, timings->vsw, | ||
| 2351 | timings->vfp, timings->vbp)) | ||
| 2352 | BUG(); | 2673 | BUG(); |
| 2674 | return; | ||
| 2675 | } | ||
| 2676 | |||
| 2677 | if (dispc_mgr_is_lcd(channel)) { | ||
| 2678 | _dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw, | ||
| 2679 | t.vfp, t.vbp); | ||
| 2680 | |||
| 2681 | xtot = t.x_res + t.hfp + t.hsw + t.hbp; | ||
| 2682 | ytot = t.y_res + t.vfp + t.vsw + t.vbp; | ||
| 2353 | 2683 | ||
| 2354 | _dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp, | 2684 | ht = (timings->pixel_clock * 1000) / xtot; |
| 2355 | timings->hbp, timings->vsw, timings->vfp, | 2685 | vt = (timings->pixel_clock * 1000) / xtot / ytot; |
| 2356 | timings->vbp); | ||
| 2357 | 2686 | ||
| 2358 | dispc_mgr_set_lcd_size(channel, timings->x_res, timings->y_res); | 2687 | DSSDBG("pck %u\n", timings->pixel_clock); |
| 2688 | DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", | ||
| 2689 | t.hsw, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp); | ||
| 2359 | 2690 | ||
| 2360 | xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; | 2691 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); |
| 2361 | ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; | 2692 | } else { |
| 2693 | enum dss_hdmi_venc_clk_source_select source; | ||
| 2362 | 2694 | ||
| 2363 | ht = (timings->pixel_clock * 1000) / xtot; | 2695 | source = dss_get_hdmi_venc_clk_source(); |
| 2364 | vt = (timings->pixel_clock * 1000) / xtot / ytot; | ||
| 2365 | 2696 | ||
| 2366 | DSSDBG("channel %d xres %u yres %u\n", channel, timings->x_res, | 2697 | if (source == DSS_VENC_TV_CLK) |
| 2367 | timings->y_res); | 2698 | t.y_res /= 2; |
| 2368 | DSSDBG("pck %u\n", timings->pixel_clock); | 2699 | } |
| 2369 | DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", | ||
| 2370 | timings->hsw, timings->hfp, timings->hbp, | ||
| 2371 | timings->vsw, timings->vfp, timings->vbp); | ||
| 2372 | 2700 | ||
| 2373 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); | 2701 | dispc_mgr_set_size(channel, t.x_res, t.y_res); |
| 2374 | } | 2702 | } |
| 2375 | 2703 | ||
| 2376 | static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, | 2704 | static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, |
| @@ -2411,6 +2739,7 @@ unsigned long dispc_fclk_rate(void) | |||
| 2411 | break; | 2739 | break; |
| 2412 | default: | 2740 | default: |
| 2413 | BUG(); | 2741 | BUG(); |
| 2742 | return 0; | ||
| 2414 | } | 2743 | } |
| 2415 | 2744 | ||
| 2416 | return r; | 2745 | return r; |
| @@ -2441,6 +2770,7 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) | |||
| 2441 | break; | 2770 | break; |
| 2442 | default: | 2771 | default: |
| 2443 | BUG(); | 2772 | BUG(); |
| 2773 | return 0; | ||
| 2444 | } | 2774 | } |
| 2445 | 2775 | ||
| 2446 | return r / lcd; | 2776 | return r / lcd; |
| @@ -2462,20 +2792,35 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) | |||
| 2462 | 2792 | ||
| 2463 | return r / pcd; | 2793 | return r / pcd; |
| 2464 | } else { | 2794 | } else { |
| 2465 | struct omap_dss_device *dssdev = | 2795 | enum dss_hdmi_venc_clk_source_select source; |
| 2466 | dispc_mgr_get_device(channel); | ||
| 2467 | 2796 | ||
| 2468 | switch (dssdev->type) { | 2797 | source = dss_get_hdmi_venc_clk_source(); |
| 2469 | case OMAP_DISPLAY_TYPE_VENC: | 2798 | |
| 2799 | switch (source) { | ||
| 2800 | case DSS_VENC_TV_CLK: | ||
| 2470 | return venc_get_pixel_clock(); | 2801 | return venc_get_pixel_clock(); |
| 2471 | case OMAP_DISPLAY_TYPE_HDMI: | 2802 | case DSS_HDMI_M_PCLK: |
| 2472 | return hdmi_get_pixel_clock(); | 2803 | return hdmi_get_pixel_clock(); |
| 2473 | default: | 2804 | default: |
| 2474 | BUG(); | 2805 | BUG(); |
| 2806 | return 0; | ||
| 2475 | } | 2807 | } |
| 2476 | } | 2808 | } |
| 2477 | } | 2809 | } |
| 2478 | 2810 | ||
| 2811 | unsigned long dispc_core_clk_rate(void) | ||
| 2812 | { | ||
| 2813 | int lcd; | ||
| 2814 | unsigned long fclk = dispc_fclk_rate(); | ||
| 2815 | |||
| 2816 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | ||
| 2817 | lcd = REG_GET(DISPC_DIVISOR, 23, 16); | ||
| 2818 | else | ||
| 2819 | lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16); | ||
| 2820 | |||
| 2821 | return fclk / lcd; | ||
| 2822 | } | ||
| 2823 | |||
| 2479 | void dispc_dump_clocks(struct seq_file *s) | 2824 | void dispc_dump_clocks(struct seq_file *s) |
| 2480 | { | 2825 | { |
| 2481 | int lcd, pcd; | 2826 | int lcd, pcd; |
| @@ -2588,7 +2933,7 @@ void dispc_dump_irqs(struct seq_file *s) | |||
| 2588 | } | 2933 | } |
| 2589 | #endif | 2934 | #endif |
| 2590 | 2935 | ||
| 2591 | void dispc_dump_regs(struct seq_file *s) | 2936 | static void dispc_dump_regs(struct seq_file *s) |
| 2592 | { | 2937 | { |
| 2593 | int i, j; | 2938 | int i, j; |
| 2594 | const char *mgr_names[] = { | 2939 | const char *mgr_names[] = { |
| @@ -3247,27 +3592,6 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, | |||
| 3247 | return 0; | 3592 | return 0; |
| 3248 | } | 3593 | } |
| 3249 | 3594 | ||
| 3250 | #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC | ||
| 3251 | void dispc_fake_vsync_irq(void) | ||
| 3252 | { | ||
| 3253 | u32 irqstatus = DISPC_IRQ_VSYNC; | ||
| 3254 | int i; | ||
| 3255 | |||
| 3256 | WARN_ON(!in_interrupt()); | ||
| 3257 | |||
| 3258 | for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { | ||
| 3259 | struct omap_dispc_isr_data *isr_data; | ||
| 3260 | isr_data = &dispc.registered_isr[i]; | ||
| 3261 | |||
| 3262 | if (!isr_data->isr) | ||
| 3263 | continue; | ||
| 3264 | |||
| 3265 | if (isr_data->mask & irqstatus) | ||
| 3266 | isr_data->isr(isr_data->arg, irqstatus); | ||
| 3267 | } | ||
| 3268 | } | ||
| 3269 | #endif | ||
| 3270 | |||
| 3271 | static void _omap_dispc_initialize_irq(void) | 3595 | static void _omap_dispc_initialize_irq(void) |
| 3272 | { | 3596 | { |
| 3273 | unsigned long flags; | 3597 | unsigned long flags; |
| @@ -3330,7 +3654,7 @@ static void _omap_dispc_initial_config(void) | |||
| 3330 | } | 3654 | } |
| 3331 | 3655 | ||
| 3332 | /* DISPC HW IP initialisation */ | 3656 | /* DISPC HW IP initialisation */ |
| 3333 | static int omap_dispchw_probe(struct platform_device *pdev) | 3657 | static int __init omap_dispchw_probe(struct platform_device *pdev) |
| 3334 | { | 3658 | { |
| 3335 | u32 rev; | 3659 | u32 rev; |
| 3336 | int r = 0; | 3660 | int r = 0; |
| @@ -3399,6 +3723,11 @@ static int omap_dispchw_probe(struct platform_device *pdev) | |||
| 3399 | 3723 | ||
| 3400 | dispc_runtime_put(); | 3724 | dispc_runtime_put(); |
| 3401 | 3725 | ||
| 3726 | dss_debugfs_create_file("dispc", dispc_dump_regs); | ||
| 3727 | |||
| 3728 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
| 3729 | dss_debugfs_create_file("dispc_irq", dispc_dump_irqs); | ||
| 3730 | #endif | ||
| 3402 | return 0; | 3731 | return 0; |
| 3403 | 3732 | ||
| 3404 | err_runtime_get: | 3733 | err_runtime_get: |
| @@ -3407,7 +3736,7 @@ err_runtime_get: | |||
| 3407 | return r; | 3736 | return r; |
| 3408 | } | 3737 | } |
| 3409 | 3738 | ||
| 3410 | static int omap_dispchw_remove(struct platform_device *pdev) | 3739 | static int __exit omap_dispchw_remove(struct platform_device *pdev) |
| 3411 | { | 3740 | { |
| 3412 | pm_runtime_disable(&pdev->dev); | 3741 | pm_runtime_disable(&pdev->dev); |
| 3413 | 3742 | ||
| @@ -3419,19 +3748,12 @@ static int omap_dispchw_remove(struct platform_device *pdev) | |||
| 3419 | static int dispc_runtime_suspend(struct device *dev) | 3748 | static int dispc_runtime_suspend(struct device *dev) |
| 3420 | { | 3749 | { |
| 3421 | dispc_save_context(); | 3750 | dispc_save_context(); |
| 3422 | dss_runtime_put(); | ||
| 3423 | 3751 | ||
| 3424 | return 0; | 3752 | return 0; |
| 3425 | } | 3753 | } |
| 3426 | 3754 | ||
| 3427 | static int dispc_runtime_resume(struct device *dev) | 3755 | static int dispc_runtime_resume(struct device *dev) |
| 3428 | { | 3756 | { |
| 3429 | int r; | ||
| 3430 | |||
| 3431 | r = dss_runtime_get(); | ||
| 3432 | if (r < 0) | ||
| 3433 | return r; | ||
| 3434 | |||
| 3435 | dispc_restore_context(); | 3757 | dispc_restore_context(); |
| 3436 | 3758 | ||
| 3437 | return 0; | 3759 | return 0; |
| @@ -3443,8 +3765,7 @@ static const struct dev_pm_ops dispc_pm_ops = { | |||
| 3443 | }; | 3765 | }; |
| 3444 | 3766 | ||
| 3445 | static struct platform_driver omap_dispchw_driver = { | 3767 | static struct platform_driver omap_dispchw_driver = { |
| 3446 | .probe = omap_dispchw_probe, | 3768 | .remove = __exit_p(omap_dispchw_remove), |
| 3447 | .remove = omap_dispchw_remove, | ||
| 3448 | .driver = { | 3769 | .driver = { |
| 3449 | .name = "omapdss_dispc", | 3770 | .name = "omapdss_dispc", |
| 3450 | .owner = THIS_MODULE, | 3771 | .owner = THIS_MODULE, |
| @@ -3452,12 +3773,12 @@ static struct platform_driver omap_dispchw_driver = { | |||
| 3452 | }, | 3773 | }, |
| 3453 | }; | 3774 | }; |
| 3454 | 3775 | ||
| 3455 | int dispc_init_platform_driver(void) | 3776 | int __init dispc_init_platform_driver(void) |
| 3456 | { | 3777 | { |
| 3457 | return platform_driver_register(&omap_dispchw_driver); | 3778 | return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe); |
| 3458 | } | 3779 | } |
| 3459 | 3780 | ||
| 3460 | void dispc_uninit_platform_driver(void) | 3781 | void __exit dispc_uninit_platform_driver(void) |
| 3461 | { | 3782 | { |
| 3462 | return platform_driver_unregister(&omap_dispchw_driver); | 3783 | platform_driver_unregister(&omap_dispchw_driver); |
| 3463 | } | 3784 | } |
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h index 5836bd1650f9..f278080e1063 100644 --- a/drivers/video/omap2/dss/dispc.h +++ b/drivers/video/omap2/dss/dispc.h | |||
| @@ -120,6 +120,7 @@ static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel) | |||
| 120 | return 0x03AC; | 120 | return 0x03AC; |
| 121 | default: | 121 | default: |
| 122 | BUG(); | 122 | BUG(); |
| 123 | return 0; | ||
| 123 | } | 124 | } |
| 124 | } | 125 | } |
| 125 | 126 | ||
| @@ -134,6 +135,7 @@ static inline u16 DISPC_TRANS_COLOR(enum omap_channel channel) | |||
| 134 | return 0x03B0; | 135 | return 0x03B0; |
| 135 | default: | 136 | default: |
| 136 | BUG(); | 137 | BUG(); |
| 138 | return 0; | ||
| 137 | } | 139 | } |
| 138 | } | 140 | } |
| 139 | 141 | ||
| @@ -144,10 +146,12 @@ static inline u16 DISPC_TIMING_H(enum omap_channel channel) | |||
| 144 | return 0x0064; | 146 | return 0x0064; |
| 145 | case OMAP_DSS_CHANNEL_DIGIT: | 147 | case OMAP_DSS_CHANNEL_DIGIT: |
| 146 | BUG(); | 148 | BUG(); |
| 149 | return 0; | ||
| 147 | case OMAP_DSS_CHANNEL_LCD2: | 150 | case OMAP_DSS_CHANNEL_LCD2: |
| 148 | return 0x0400; | 151 | return 0x0400; |
| 149 | default: | 152 | default: |
| 150 | BUG(); | 153 | BUG(); |
| 154 | return 0; | ||
| 151 | } | 155 | } |
| 152 | } | 156 | } |
| 153 | 157 | ||
| @@ -158,10 +162,12 @@ static inline u16 DISPC_TIMING_V(enum omap_channel channel) | |||
| 158 | return 0x0068; | 162 | return 0x0068; |
| 159 | case OMAP_DSS_CHANNEL_DIGIT: | 163 | case OMAP_DSS_CHANNEL_DIGIT: |
| 160 | BUG(); | 164 | BUG(); |
| 165 | return 0; | ||
| 161 | case OMAP_DSS_CHANNEL_LCD2: | 166 | case OMAP_DSS_CHANNEL_LCD2: |
| 162 | return 0x0404; | 167 | return 0x0404; |
| 163 | default: | 168 | default: |
| 164 | BUG(); | 169 | BUG(); |
| 170 | return 0; | ||
| 165 | } | 171 | } |
| 166 | } | 172 | } |
| 167 | 173 | ||
| @@ -172,10 +178,12 @@ static inline u16 DISPC_POL_FREQ(enum omap_channel channel) | |||
| 172 | return 0x006C; | 178 | return 0x006C; |
| 173 | case OMAP_DSS_CHANNEL_DIGIT: | 179 | case OMAP_DSS_CHANNEL_DIGIT: |
| 174 | BUG(); | 180 | BUG(); |
| 181 | return 0; | ||
| 175 | case OMAP_DSS_CHANNEL_LCD2: | 182 | case OMAP_DSS_CHANNEL_LCD2: |
| 176 | return 0x0408; | 183 | return 0x0408; |
| 177 | default: | 184 | default: |
| 178 | BUG(); | 185 | BUG(); |
| 186 | return 0; | ||
| 179 | } | 187 | } |
| 180 | } | 188 | } |
| 181 | 189 | ||
| @@ -186,10 +194,12 @@ static inline u16 DISPC_DIVISORo(enum omap_channel channel) | |||
| 186 | return 0x0070; | 194 | return 0x0070; |
| 187 | case OMAP_DSS_CHANNEL_DIGIT: | 195 | case OMAP_DSS_CHANNEL_DIGIT: |
| 188 | BUG(); | 196 | BUG(); |
| 197 | return 0; | ||
| 189 | case OMAP_DSS_CHANNEL_LCD2: | 198 | case OMAP_DSS_CHANNEL_LCD2: |
| 190 | return 0x040C; | 199 | return 0x040C; |
| 191 | default: | 200 | default: |
| 192 | BUG(); | 201 | BUG(); |
| 202 | return 0; | ||
| 193 | } | 203 | } |
| 194 | } | 204 | } |
| 195 | 205 | ||
| @@ -205,6 +215,7 @@ static inline u16 DISPC_SIZE_MGR(enum omap_channel channel) | |||
| 205 | return 0x03CC; | 215 | return 0x03CC; |
| 206 | default: | 216 | default: |
| 207 | BUG(); | 217 | BUG(); |
| 218 | return 0; | ||
| 208 | } | 219 | } |
| 209 | } | 220 | } |
| 210 | 221 | ||
| @@ -215,10 +226,12 @@ static inline u16 DISPC_DATA_CYCLE1(enum omap_channel channel) | |||
| 215 | return 0x01D4; | 226 | return 0x01D4; |
| 216 | case OMAP_DSS_CHANNEL_DIGIT: | 227 | case OMAP_DSS_CHANNEL_DIGIT: |
| 217 | BUG(); | 228 | BUG(); |
| 229 | return 0; | ||
| 218 | case OMAP_DSS_CHANNEL_LCD2: | 230 | case OMAP_DSS_CHANNEL_LCD2: |
| 219 | return 0x03C0; | 231 | return 0x03C0; |
| 220 | default: | 232 | default: |
| 221 | BUG(); | 233 | BUG(); |
| 234 | return 0; | ||
| 222 | } | 235 | } |
| 223 | } | 236 | } |
| 224 | 237 | ||
| @@ -229,10 +242,12 @@ static inline u16 DISPC_DATA_CYCLE2(enum omap_channel channel) | |||
| 229 | return 0x01D8; | 242 | return 0x01D8; |
| 230 | case OMAP_DSS_CHANNEL_DIGIT: | 243 | case OMAP_DSS_CHANNEL_DIGIT: |
| 231 | BUG(); | 244 | BUG(); |
| 245 | return 0; | ||
| 232 | case OMAP_DSS_CHANNEL_LCD2: | 246 | case OMAP_DSS_CHANNEL_LCD2: |
| 233 | return 0x03C4; | 247 | return 0x03C4; |
| 234 | default: | 248 | default: |
| 235 | BUG(); | 249 | BUG(); |
| 250 | return 0; | ||
| 236 | } | 251 | } |
| 237 | } | 252 | } |
| 238 | 253 | ||
| @@ -243,10 +258,12 @@ static inline u16 DISPC_DATA_CYCLE3(enum omap_channel channel) | |||
| 243 | return 0x01DC; | 258 | return 0x01DC; |
| 244 | case OMAP_DSS_CHANNEL_DIGIT: | 259 | case OMAP_DSS_CHANNEL_DIGIT: |
| 245 | BUG(); | 260 | BUG(); |
| 261 | return 0; | ||
| 246 | case OMAP_DSS_CHANNEL_LCD2: | 262 | case OMAP_DSS_CHANNEL_LCD2: |
| 247 | return 0x03C8; | 263 | return 0x03C8; |
| 248 | default: | 264 | default: |
| 249 | BUG(); | 265 | BUG(); |
| 266 | return 0; | ||
| 250 | } | 267 | } |
| 251 | } | 268 | } |
| 252 | 269 | ||
| @@ -257,10 +274,12 @@ static inline u16 DISPC_CPR_COEF_R(enum omap_channel channel) | |||
| 257 | return 0x0220; | 274 | return 0x0220; |
| 258 | case OMAP_DSS_CHANNEL_DIGIT: | 275 | case OMAP_DSS_CHANNEL_DIGIT: |
| 259 | BUG(); | 276 | BUG(); |
| 277 | return 0; | ||
| 260 | case OMAP_DSS_CHANNEL_LCD2: | 278 | case OMAP_DSS_CHANNEL_LCD2: |
| 261 | return 0x03BC; | 279 | return 0x03BC; |
| 262 | default: | 280 | default: |
| 263 | BUG(); | 281 | BUG(); |
| 282 | return 0; | ||
| 264 | } | 283 | } |
| 265 | } | 284 | } |
| 266 | 285 | ||
| @@ -271,10 +290,12 @@ static inline u16 DISPC_CPR_COEF_G(enum omap_channel channel) | |||
| 271 | return 0x0224; | 290 | return 0x0224; |
| 272 | case OMAP_DSS_CHANNEL_DIGIT: | 291 | case OMAP_DSS_CHANNEL_DIGIT: |
| 273 | BUG(); | 292 | BUG(); |
| 293 | return 0; | ||
| 274 | case OMAP_DSS_CHANNEL_LCD2: | 294 | case OMAP_DSS_CHANNEL_LCD2: |
| 275 | return 0x03B8; | 295 | return 0x03B8; |
| 276 | default: | 296 | default: |
| 277 | BUG(); | 297 | BUG(); |
| 298 | return 0; | ||
| 278 | } | 299 | } |
| 279 | } | 300 | } |
| 280 | 301 | ||
| @@ -285,10 +306,12 @@ static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel) | |||
| 285 | return 0x0228; | 306 | return 0x0228; |
| 286 | case OMAP_DSS_CHANNEL_DIGIT: | 307 | case OMAP_DSS_CHANNEL_DIGIT: |
| 287 | BUG(); | 308 | BUG(); |
| 309 | return 0; | ||
| 288 | case OMAP_DSS_CHANNEL_LCD2: | 310 | case OMAP_DSS_CHANNEL_LCD2: |
| 289 | return 0x03B4; | 311 | return 0x03B4; |
| 290 | default: | 312 | default: |
| 291 | BUG(); | 313 | BUG(); |
| 314 | return 0; | ||
| 292 | } | 315 | } |
| 293 | } | 316 | } |
| 294 | 317 | ||
| @@ -306,6 +329,7 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane) | |||
| 306 | return 0x0300; | 329 | return 0x0300; |
| 307 | default: | 330 | default: |
| 308 | BUG(); | 331 | BUG(); |
| 332 | return 0; | ||
| 309 | } | 333 | } |
| 310 | } | 334 | } |
| 311 | 335 | ||
| @@ -321,6 +345,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane) | |||
| 321 | return 0x0008; | 345 | return 0x0008; |
| 322 | default: | 346 | default: |
| 323 | BUG(); | 347 | BUG(); |
| 348 | return 0; | ||
| 324 | } | 349 | } |
| 325 | } | 350 | } |
| 326 | 351 | ||
| @@ -335,6 +360,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane) | |||
| 335 | return 0x000C; | 360 | return 0x000C; |
| 336 | default: | 361 | default: |
| 337 | BUG(); | 362 | BUG(); |
| 363 | return 0; | ||
| 338 | } | 364 | } |
| 339 | } | 365 | } |
| 340 | 366 | ||
| @@ -343,6 +369,7 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane) | |||
| 343 | switch (plane) { | 369 | switch (plane) { |
| 344 | case OMAP_DSS_GFX: | 370 | case OMAP_DSS_GFX: |
| 345 | BUG(); | 371 | BUG(); |
| 372 | return 0; | ||
| 346 | case OMAP_DSS_VIDEO1: | 373 | case OMAP_DSS_VIDEO1: |
| 347 | return 0x0544; | 374 | return 0x0544; |
| 348 | case OMAP_DSS_VIDEO2: | 375 | case OMAP_DSS_VIDEO2: |
| @@ -351,6 +378,7 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane) | |||
| 351 | return 0x0310; | 378 | return 0x0310; |
| 352 | default: | 379 | default: |
| 353 | BUG(); | 380 | BUG(); |
| 381 | return 0; | ||
| 354 | } | 382 | } |
| 355 | } | 383 | } |
| 356 | 384 | ||
| @@ -359,6 +387,7 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane) | |||
| 359 | switch (plane) { | 387 | switch (plane) { |
| 360 | case OMAP_DSS_GFX: | 388 | case OMAP_DSS_GFX: |
| 361 | BUG(); | 389 | BUG(); |
| 390 | return 0; | ||
| 362 | case OMAP_DSS_VIDEO1: | 391 | case OMAP_DSS_VIDEO1: |
| 363 | return 0x0548; | 392 | return 0x0548; |
| 364 | case OMAP_DSS_VIDEO2: | 393 | case OMAP_DSS_VIDEO2: |
| @@ -367,6 +396,7 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane) | |||
| 367 | return 0x0314; | 396 | return 0x0314; |
| 368 | default: | 397 | default: |
| 369 | BUG(); | 398 | BUG(); |
| 399 | return 0; | ||
| 370 | } | 400 | } |
| 371 | } | 401 | } |
| 372 | 402 | ||
| @@ -381,6 +411,7 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane) | |||
| 381 | return 0x009C; | 411 | return 0x009C; |
| 382 | default: | 412 | default: |
| 383 | BUG(); | 413 | BUG(); |
| 414 | return 0; | ||
| 384 | } | 415 | } |
| 385 | } | 416 | } |
| 386 | 417 | ||
| @@ -395,6 +426,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane) | |||
| 395 | return 0x00A8; | 426 | return 0x00A8; |
| 396 | default: | 427 | default: |
| 397 | BUG(); | 428 | BUG(); |
| 429 | return 0; | ||
| 398 | } | 430 | } |
| 399 | } | 431 | } |
| 400 | 432 | ||
| @@ -410,6 +442,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane) | |||
| 410 | return 0x0070; | 442 | return 0x0070; |
| 411 | default: | 443 | default: |
| 412 | BUG(); | 444 | BUG(); |
| 445 | return 0; | ||
| 413 | } | 446 | } |
| 414 | } | 447 | } |
| 415 | 448 | ||
| @@ -418,6 +451,7 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane) | |||
| 418 | switch (plane) { | 451 | switch (plane) { |
| 419 | case OMAP_DSS_GFX: | 452 | case OMAP_DSS_GFX: |
| 420 | BUG(); | 453 | BUG(); |
| 454 | return 0; | ||
| 421 | case OMAP_DSS_VIDEO1: | 455 | case OMAP_DSS_VIDEO1: |
| 422 | return 0x0568; | 456 | return 0x0568; |
| 423 | case OMAP_DSS_VIDEO2: | 457 | case OMAP_DSS_VIDEO2: |
| @@ -426,6 +460,7 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane) | |||
| 426 | return 0x032C; | 460 | return 0x032C; |
| 427 | default: | 461 | default: |
| 428 | BUG(); | 462 | BUG(); |
| 463 | return 0; | ||
| 429 | } | 464 | } |
| 430 | } | 465 | } |
| 431 | 466 | ||
| @@ -441,6 +476,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane) | |||
| 441 | return 0x008C; | 476 | return 0x008C; |
| 442 | default: | 477 | default: |
| 443 | BUG(); | 478 | BUG(); |
| 479 | return 0; | ||
| 444 | } | 480 | } |
| 445 | } | 481 | } |
| 446 | 482 | ||
| @@ -456,6 +492,7 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane) | |||
| 456 | return 0x0088; | 492 | return 0x0088; |
| 457 | default: | 493 | default: |
| 458 | BUG(); | 494 | BUG(); |
| 495 | return 0; | ||
| 459 | } | 496 | } |
| 460 | } | 497 | } |
| 461 | 498 | ||
| @@ -471,6 +508,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane) | |||
| 471 | return 0x00A4; | 508 | return 0x00A4; |
| 472 | default: | 509 | default: |
| 473 | BUG(); | 510 | BUG(); |
| 511 | return 0; | ||
| 474 | } | 512 | } |
| 475 | } | 513 | } |
| 476 | 514 | ||
| @@ -486,6 +524,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane) | |||
| 486 | return 0x0098; | 524 | return 0x0098; |
| 487 | default: | 525 | default: |
| 488 | BUG(); | 526 | BUG(); |
| 527 | return 0; | ||
| 489 | } | 528 | } |
| 490 | } | 529 | } |
| 491 | 530 | ||
| @@ -498,8 +537,10 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane) | |||
| 498 | case OMAP_DSS_VIDEO2: | 537 | case OMAP_DSS_VIDEO2: |
| 499 | case OMAP_DSS_VIDEO3: | 538 | case OMAP_DSS_VIDEO3: |
| 500 | BUG(); | 539 | BUG(); |
| 540 | return 0; | ||
| 501 | default: | 541 | default: |
| 502 | BUG(); | 542 | BUG(); |
| 543 | return 0; | ||
| 503 | } | 544 | } |
| 504 | } | 545 | } |
| 505 | 546 | ||
| @@ -512,8 +553,10 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane) | |||
| 512 | case OMAP_DSS_VIDEO2: | 553 | case OMAP_DSS_VIDEO2: |
| 513 | case OMAP_DSS_VIDEO3: | 554 | case OMAP_DSS_VIDEO3: |
| 514 | BUG(); | 555 | BUG(); |
| 556 | return 0; | ||
| 515 | default: | 557 | default: |
| 516 | BUG(); | 558 | BUG(); |
| 559 | return 0; | ||
| 517 | } | 560 | } |
| 518 | } | 561 | } |
| 519 | 562 | ||
| @@ -522,6 +565,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane) | |||
| 522 | switch (plane) { | 565 | switch (plane) { |
| 523 | case OMAP_DSS_GFX: | 566 | case OMAP_DSS_GFX: |
| 524 | BUG(); | 567 | BUG(); |
| 568 | return 0; | ||
| 525 | case OMAP_DSS_VIDEO1: | 569 | case OMAP_DSS_VIDEO1: |
| 526 | case OMAP_DSS_VIDEO2: | 570 | case OMAP_DSS_VIDEO2: |
| 527 | return 0x0024; | 571 | return 0x0024; |
| @@ -529,6 +573,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane) | |||
| 529 | return 0x0090; | 573 | return 0x0090; |
| 530 | default: | 574 | default: |
| 531 | BUG(); | 575 | BUG(); |
| 576 | return 0; | ||
| 532 | } | 577 | } |
| 533 | } | 578 | } |
| 534 | 579 | ||
| @@ -537,6 +582,7 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane) | |||
| 537 | switch (plane) { | 582 | switch (plane) { |
| 538 | case OMAP_DSS_GFX: | 583 | case OMAP_DSS_GFX: |
| 539 | BUG(); | 584 | BUG(); |
| 585 | return 0; | ||
| 540 | case OMAP_DSS_VIDEO1: | 586 | case OMAP_DSS_VIDEO1: |
| 541 | return 0x0580; | 587 | return 0x0580; |
| 542 | case OMAP_DSS_VIDEO2: | 588 | case OMAP_DSS_VIDEO2: |
| @@ -545,6 +591,7 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane) | |||
| 545 | return 0x0424; | 591 | return 0x0424; |
| 546 | default: | 592 | default: |
| 547 | BUG(); | 593 | BUG(); |
| 594 | return 0; | ||
| 548 | } | 595 | } |
| 549 | } | 596 | } |
| 550 | 597 | ||
| @@ -553,6 +600,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane) | |||
| 553 | switch (plane) { | 600 | switch (plane) { |
| 554 | case OMAP_DSS_GFX: | 601 | case OMAP_DSS_GFX: |
| 555 | BUG(); | 602 | BUG(); |
| 603 | return 0; | ||
| 556 | case OMAP_DSS_VIDEO1: | 604 | case OMAP_DSS_VIDEO1: |
| 557 | case OMAP_DSS_VIDEO2: | 605 | case OMAP_DSS_VIDEO2: |
| 558 | return 0x0028; | 606 | return 0x0028; |
| @@ -560,6 +608,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane) | |||
| 560 | return 0x0094; | 608 | return 0x0094; |
| 561 | default: | 609 | default: |
| 562 | BUG(); | 610 | BUG(); |
| 611 | return 0; | ||
| 563 | } | 612 | } |
| 564 | } | 613 | } |
| 565 | 614 | ||
| @@ -569,6 +618,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane) | |||
| 569 | switch (plane) { | 618 | switch (plane) { |
| 570 | case OMAP_DSS_GFX: | 619 | case OMAP_DSS_GFX: |
| 571 | BUG(); | 620 | BUG(); |
| 621 | return 0; | ||
| 572 | case OMAP_DSS_VIDEO1: | 622 | case OMAP_DSS_VIDEO1: |
| 573 | case OMAP_DSS_VIDEO2: | 623 | case OMAP_DSS_VIDEO2: |
| 574 | return 0x002C; | 624 | return 0x002C; |
| @@ -576,6 +626,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane) | |||
| 576 | return 0x0000; | 626 | return 0x0000; |
| 577 | default: | 627 | default: |
| 578 | BUG(); | 628 | BUG(); |
| 629 | return 0; | ||
| 579 | } | 630 | } |
| 580 | } | 631 | } |
| 581 | 632 | ||
| @@ -584,6 +635,7 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane) | |||
| 584 | switch (plane) { | 635 | switch (plane) { |
| 585 | case OMAP_DSS_GFX: | 636 | case OMAP_DSS_GFX: |
| 586 | BUG(); | 637 | BUG(); |
| 638 | return 0; | ||
| 587 | case OMAP_DSS_VIDEO1: | 639 | case OMAP_DSS_VIDEO1: |
| 588 | return 0x0584; | 640 | return 0x0584; |
| 589 | case OMAP_DSS_VIDEO2: | 641 | case OMAP_DSS_VIDEO2: |
| @@ -592,6 +644,7 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane) | |||
| 592 | return 0x0428; | 644 | return 0x0428; |
| 593 | default: | 645 | default: |
| 594 | BUG(); | 646 | BUG(); |
| 647 | return 0; | ||
| 595 | } | 648 | } |
| 596 | } | 649 | } |
| 597 | 650 | ||
| @@ -600,6 +653,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane) | |||
| 600 | switch (plane) { | 653 | switch (plane) { |
| 601 | case OMAP_DSS_GFX: | 654 | case OMAP_DSS_GFX: |
| 602 | BUG(); | 655 | BUG(); |
| 656 | return 0; | ||
| 603 | case OMAP_DSS_VIDEO1: | 657 | case OMAP_DSS_VIDEO1: |
| 604 | case OMAP_DSS_VIDEO2: | 658 | case OMAP_DSS_VIDEO2: |
| 605 | return 0x0030; | 659 | return 0x0030; |
| @@ -607,6 +661,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane) | |||
| 607 | return 0x0004; | 661 | return 0x0004; |
| 608 | default: | 662 | default: |
| 609 | BUG(); | 663 | BUG(); |
| 664 | return 0; | ||
| 610 | } | 665 | } |
| 611 | } | 666 | } |
| 612 | 667 | ||
| @@ -615,6 +670,7 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane) | |||
| 615 | switch (plane) { | 670 | switch (plane) { |
| 616 | case OMAP_DSS_GFX: | 671 | case OMAP_DSS_GFX: |
| 617 | BUG(); | 672 | BUG(); |
| 673 | return 0; | ||
| 618 | case OMAP_DSS_VIDEO1: | 674 | case OMAP_DSS_VIDEO1: |
| 619 | return 0x0588; | 675 | return 0x0588; |
| 620 | case OMAP_DSS_VIDEO2: | 676 | case OMAP_DSS_VIDEO2: |
| @@ -623,6 +679,7 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane) | |||
| 623 | return 0x042C; | 679 | return 0x042C; |
| 624 | default: | 680 | default: |
| 625 | BUG(); | 681 | BUG(); |
| 682 | return 0; | ||
| 626 | } | 683 | } |
| 627 | } | 684 | } |
| 628 | 685 | ||
| @@ -632,6 +689,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i) | |||
| 632 | switch (plane) { | 689 | switch (plane) { |
| 633 | case OMAP_DSS_GFX: | 690 | case OMAP_DSS_GFX: |
| 634 | BUG(); | 691 | BUG(); |
| 692 | return 0; | ||
| 635 | case OMAP_DSS_VIDEO1: | 693 | case OMAP_DSS_VIDEO1: |
| 636 | case OMAP_DSS_VIDEO2: | 694 | case OMAP_DSS_VIDEO2: |
| 637 | return 0x0034 + i * 0x8; | 695 | return 0x0034 + i * 0x8; |
| @@ -639,6 +697,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i) | |||
| 639 | return 0x0010 + i * 0x8; | 697 | return 0x0010 + i * 0x8; |
| 640 | default: | 698 | default: |
| 641 | BUG(); | 699 | BUG(); |
| 700 | return 0; | ||
| 642 | } | 701 | } |
| 643 | } | 702 | } |
| 644 | 703 | ||
| @@ -648,6 +707,7 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i) | |||
| 648 | switch (plane) { | 707 | switch (plane) { |
| 649 | case OMAP_DSS_GFX: | 708 | case OMAP_DSS_GFX: |
| 650 | BUG(); | 709 | BUG(); |
| 710 | return 0; | ||
| 651 | case OMAP_DSS_VIDEO1: | 711 | case OMAP_DSS_VIDEO1: |
| 652 | return 0x058C + i * 0x8; | 712 | return 0x058C + i * 0x8; |
| 653 | case OMAP_DSS_VIDEO2: | 713 | case OMAP_DSS_VIDEO2: |
| @@ -656,6 +716,7 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i) | |||
| 656 | return 0x0430 + i * 0x8; | 716 | return 0x0430 + i * 0x8; |
| 657 | default: | 717 | default: |
| 658 | BUG(); | 718 | BUG(); |
| 719 | return 0; | ||
| 659 | } | 720 | } |
| 660 | } | 721 | } |
| 661 | 722 | ||
| @@ -665,6 +726,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i) | |||
| 665 | switch (plane) { | 726 | switch (plane) { |
| 666 | case OMAP_DSS_GFX: | 727 | case OMAP_DSS_GFX: |
| 667 | BUG(); | 728 | BUG(); |
| 729 | return 0; | ||
| 668 | case OMAP_DSS_VIDEO1: | 730 | case OMAP_DSS_VIDEO1: |
| 669 | case OMAP_DSS_VIDEO2: | 731 | case OMAP_DSS_VIDEO2: |
| 670 | return 0x0038 + i * 0x8; | 732 | return 0x0038 + i * 0x8; |
| @@ -672,6 +734,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i) | |||
| 672 | return 0x0014 + i * 0x8; | 734 | return 0x0014 + i * 0x8; |
| 673 | default: | 735 | default: |
| 674 | BUG(); | 736 | BUG(); |
| 737 | return 0; | ||
| 675 | } | 738 | } |
| 676 | } | 739 | } |
| 677 | 740 | ||
| @@ -681,6 +744,7 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i) | |||
| 681 | switch (plane) { | 744 | switch (plane) { |
| 682 | case OMAP_DSS_GFX: | 745 | case OMAP_DSS_GFX: |
| 683 | BUG(); | 746 | BUG(); |
| 747 | return 0; | ||
| 684 | case OMAP_DSS_VIDEO1: | 748 | case OMAP_DSS_VIDEO1: |
| 685 | return 0x0590 + i * 8; | 749 | return 0x0590 + i * 8; |
| 686 | case OMAP_DSS_VIDEO2: | 750 | case OMAP_DSS_VIDEO2: |
| @@ -689,6 +753,7 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i) | |||
| 689 | return 0x0434 + i * 0x8; | 753 | return 0x0434 + i * 0x8; |
| 690 | default: | 754 | default: |
| 691 | BUG(); | 755 | BUG(); |
| 756 | return 0; | ||
| 692 | } | 757 | } |
| 693 | } | 758 | } |
| 694 | 759 | ||
| @@ -698,12 +763,14 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i) | |||
| 698 | switch (plane) { | 763 | switch (plane) { |
| 699 | case OMAP_DSS_GFX: | 764 | case OMAP_DSS_GFX: |
| 700 | BUG(); | 765 | BUG(); |
| 766 | return 0; | ||
| 701 | case OMAP_DSS_VIDEO1: | 767 | case OMAP_DSS_VIDEO1: |
| 702 | case OMAP_DSS_VIDEO2: | 768 | case OMAP_DSS_VIDEO2: |
| 703 | case OMAP_DSS_VIDEO3: | 769 | case OMAP_DSS_VIDEO3: |
| 704 | return 0x0074 + i * 0x4; | 770 | return 0x0074 + i * 0x4; |
| 705 | default: | 771 | default: |
| 706 | BUG(); | 772 | BUG(); |
| 773 | return 0; | ||
| 707 | } | 774 | } |
| 708 | } | 775 | } |
| 709 | 776 | ||
| @@ -713,6 +780,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i) | |||
| 713 | switch (plane) { | 780 | switch (plane) { |
| 714 | case OMAP_DSS_GFX: | 781 | case OMAP_DSS_GFX: |
| 715 | BUG(); | 782 | BUG(); |
| 783 | return 0; | ||
| 716 | case OMAP_DSS_VIDEO1: | 784 | case OMAP_DSS_VIDEO1: |
| 717 | return 0x0124 + i * 0x4; | 785 | return 0x0124 + i * 0x4; |
| 718 | case OMAP_DSS_VIDEO2: | 786 | case OMAP_DSS_VIDEO2: |
| @@ -721,6 +789,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i) | |||
| 721 | return 0x0050 + i * 0x4; | 789 | return 0x0050 + i * 0x4; |
| 722 | default: | 790 | default: |
| 723 | BUG(); | 791 | BUG(); |
| 792 | return 0; | ||
| 724 | } | 793 | } |
| 725 | } | 794 | } |
| 726 | 795 | ||
| @@ -730,6 +799,7 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i) | |||
| 730 | switch (plane) { | 799 | switch (plane) { |
| 731 | case OMAP_DSS_GFX: | 800 | case OMAP_DSS_GFX: |
| 732 | BUG(); | 801 | BUG(); |
| 802 | return 0; | ||
| 733 | case OMAP_DSS_VIDEO1: | 803 | case OMAP_DSS_VIDEO1: |
| 734 | return 0x05CC + i * 0x4; | 804 | return 0x05CC + i * 0x4; |
| 735 | case OMAP_DSS_VIDEO2: | 805 | case OMAP_DSS_VIDEO2: |
| @@ -738,6 +808,7 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i) | |||
| 738 | return 0x0470 + i * 0x4; | 808 | return 0x0470 + i * 0x4; |
| 739 | default: | 809 | default: |
| 740 | BUG(); | 810 | BUG(); |
| 811 | return 0; | ||
| 741 | } | 812 | } |
| 742 | } | 813 | } |
| 743 | 814 | ||
| @@ -754,6 +825,7 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane) | |||
| 754 | return 0x00A0; | 825 | return 0x00A0; |
| 755 | default: | 826 | default: |
| 756 | BUG(); | 827 | BUG(); |
| 828 | return 0; | ||
| 757 | } | 829 | } |
| 758 | } | 830 | } |
| 759 | #endif | 831 | #endif |
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 4424c198dbcd..249010630370 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c | |||
| @@ -304,10 +304,18 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) | |||
| 304 | return 24; | 304 | return 24; |
| 305 | default: | 305 | default: |
| 306 | BUG(); | 306 | BUG(); |
| 307 | return 0; | ||
| 307 | } | 308 | } |
| 308 | } | 309 | } |
| 309 | EXPORT_SYMBOL(omapdss_default_get_recommended_bpp); | 310 | EXPORT_SYMBOL(omapdss_default_get_recommended_bpp); |
| 310 | 311 | ||
| 312 | void omapdss_default_get_timings(struct omap_dss_device *dssdev, | ||
| 313 | struct omap_video_timings *timings) | ||
| 314 | { | ||
| 315 | *timings = dssdev->panel.timings; | ||
| 316 | } | ||
| 317 | EXPORT_SYMBOL(omapdss_default_get_timings); | ||
| 318 | |||
| 311 | /* Checks if replication logic should be used. Only use for active matrix, | 319 | /* Checks if replication logic should be used. Only use for active matrix, |
| 312 | * when overlay is in RGB12U or RGB16 mode, and LCD interface is | 320 | * when overlay is in RGB12U or RGB16 mode, and LCD interface is |
| 313 | * 18bpp or 24bpp */ | 321 | * 18bpp or 24bpp */ |
| @@ -340,6 +348,7 @@ bool dss_use_replication(struct omap_dss_device *dssdev, | |||
| 340 | break; | 348 | break; |
| 341 | default: | 349 | default: |
| 342 | BUG(); | 350 | BUG(); |
| 351 | return false; | ||
| 343 | } | 352 | } |
| 344 | 353 | ||
| 345 | return bpp > 16; | 354 | return bpp > 16; |
| @@ -352,46 +361,6 @@ void dss_init_device(struct platform_device *pdev, | |||
| 352 | int i; | 361 | int i; |
| 353 | int r; | 362 | int r; |
| 354 | 363 | ||
| 355 | switch (dssdev->type) { | ||
| 356 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
| 357 | case OMAP_DISPLAY_TYPE_DPI: | ||
| 358 | r = dpi_init_display(dssdev); | ||
| 359 | break; | ||
| 360 | #endif | ||
| 361 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
| 362 | case OMAP_DISPLAY_TYPE_DBI: | ||
| 363 | r = rfbi_init_display(dssdev); | ||
| 364 | break; | ||
| 365 | #endif | ||
| 366 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
| 367 | case OMAP_DISPLAY_TYPE_VENC: | ||
| 368 | r = venc_init_display(dssdev); | ||
| 369 | break; | ||
| 370 | #endif | ||
| 371 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
| 372 | case OMAP_DISPLAY_TYPE_SDI: | ||
| 373 | r = sdi_init_display(dssdev); | ||
| 374 | break; | ||
| 375 | #endif | ||
| 376 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
| 377 | case OMAP_DISPLAY_TYPE_DSI: | ||
| 378 | r = dsi_init_display(dssdev); | ||
| 379 | break; | ||
| 380 | #endif | ||
| 381 | case OMAP_DISPLAY_TYPE_HDMI: | ||
| 382 | r = hdmi_init_display(dssdev); | ||
| 383 | break; | ||
| 384 | default: | ||
| 385 | DSSERR("Support for display '%s' not compiled in.\n", | ||
| 386 | dssdev->name); | ||
| 387 | return; | ||
| 388 | } | ||
| 389 | |||
| 390 | if (r) { | ||
| 391 | DSSERR("failed to init display %s\n", dssdev->name); | ||
| 392 | return; | ||
| 393 | } | ||
| 394 | |||
| 395 | /* create device sysfs files */ | 364 | /* create device sysfs files */ |
| 396 | i = 0; | 365 | i = 0; |
| 397 | while ((attr = display_sysfs_attrs[i++]) != NULL) { | 366 | while ((attr = display_sysfs_attrs[i++]) != NULL) { |
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index faaf305fda27..8c2056c9537b 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c | |||
| @@ -156,7 +156,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
| 156 | t->pixel_clock = pck; | 156 | t->pixel_clock = pck; |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | dispc_mgr_set_lcd_timings(dssdev->manager->id, t); | 159 | dss_mgr_set_timings(dssdev->manager, t); |
| 160 | 160 | ||
| 161 | return 0; | 161 | return 0; |
| 162 | } | 162 | } |
| @@ -202,10 +202,6 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
| 202 | goto err_reg_enable; | 202 | goto err_reg_enable; |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | r = dss_runtime_get(); | ||
| 206 | if (r) | ||
| 207 | goto err_get_dss; | ||
| 208 | |||
| 209 | r = dispc_runtime_get(); | 205 | r = dispc_runtime_get(); |
| 210 | if (r) | 206 | if (r) |
| 211 | goto err_get_dispc; | 207 | goto err_get_dispc; |
| @@ -244,8 +240,6 @@ err_dsi_pll_init: | |||
| 244 | err_get_dsi: | 240 | err_get_dsi: |
| 245 | dispc_runtime_put(); | 241 | dispc_runtime_put(); |
| 246 | err_get_dispc: | 242 | err_get_dispc: |
| 247 | dss_runtime_put(); | ||
| 248 | err_get_dss: | ||
| 249 | if (cpu_is_omap34xx()) | 243 | if (cpu_is_omap34xx()) |
| 250 | regulator_disable(dpi.vdds_dsi_reg); | 244 | regulator_disable(dpi.vdds_dsi_reg); |
| 251 | err_reg_enable: | 245 | err_reg_enable: |
| @@ -266,7 +260,6 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) | |||
| 266 | } | 260 | } |
| 267 | 261 | ||
| 268 | dispc_runtime_put(); | 262 | dispc_runtime_put(); |
| 269 | dss_runtime_put(); | ||
| 270 | 263 | ||
| 271 | if (cpu_is_omap34xx()) | 264 | if (cpu_is_omap34xx()) |
| 272 | regulator_disable(dpi.vdds_dsi_reg); | 265 | regulator_disable(dpi.vdds_dsi_reg); |
| @@ -283,21 +276,15 @@ void dpi_set_timings(struct omap_dss_device *dssdev, | |||
| 283 | DSSDBG("dpi_set_timings\n"); | 276 | DSSDBG("dpi_set_timings\n"); |
| 284 | dssdev->panel.timings = *timings; | 277 | dssdev->panel.timings = *timings; |
| 285 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | 278 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { |
| 286 | r = dss_runtime_get(); | ||
| 287 | if (r) | ||
| 288 | return; | ||
| 289 | |||
| 290 | r = dispc_runtime_get(); | 279 | r = dispc_runtime_get(); |
| 291 | if (r) { | 280 | if (r) |
| 292 | dss_runtime_put(); | ||
| 293 | return; | 281 | return; |
| 294 | } | ||
| 295 | 282 | ||
| 296 | dpi_set_mode(dssdev); | 283 | dpi_set_mode(dssdev); |
| 297 | dispc_mgr_go(dssdev->manager->id); | ||
| 298 | 284 | ||
| 299 | dispc_runtime_put(); | 285 | dispc_runtime_put(); |
| 300 | dss_runtime_put(); | 286 | } else { |
| 287 | dss_mgr_set_timings(dssdev->manager, timings); | ||
| 301 | } | 288 | } |
| 302 | } | 289 | } |
| 303 | EXPORT_SYMBOL(dpi_set_timings); | 290 | EXPORT_SYMBOL(dpi_set_timings); |
| @@ -312,7 +299,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
| 312 | unsigned long pck; | 299 | unsigned long pck; |
| 313 | struct dispc_clock_info dispc_cinfo; | 300 | struct dispc_clock_info dispc_cinfo; |
| 314 | 301 | ||
| 315 | if (!dispc_lcd_timings_ok(timings)) | 302 | if (dss_mgr_check_timings(dssdev->manager, timings)) |
| 316 | return -EINVAL; | 303 | return -EINVAL; |
| 317 | 304 | ||
| 318 | if (timings->pixel_clock == 0) | 305 | if (timings->pixel_clock == 0) |
| @@ -352,7 +339,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
| 352 | } | 339 | } |
| 353 | EXPORT_SYMBOL(dpi_check_timings); | 340 | EXPORT_SYMBOL(dpi_check_timings); |
| 354 | 341 | ||
| 355 | int dpi_init_display(struct omap_dss_device *dssdev) | 342 | static int __init dpi_init_display(struct omap_dss_device *dssdev) |
| 356 | { | 343 | { |
| 357 | DSSDBG("init_display\n"); | 344 | DSSDBG("init_display\n"); |
| 358 | 345 | ||
| @@ -378,12 +365,58 @@ int dpi_init_display(struct omap_dss_device *dssdev) | |||
| 378 | return 0; | 365 | return 0; |
| 379 | } | 366 | } |
| 380 | 367 | ||
| 381 | int dpi_init(void) | 368 | static void __init dpi_probe_pdata(struct platform_device *pdev) |
| 382 | { | 369 | { |
| 370 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | ||
| 371 | int i, r; | ||
| 372 | |||
| 373 | for (i = 0; i < pdata->num_devices; ++i) { | ||
| 374 | struct omap_dss_device *dssdev = pdata->devices[i]; | ||
| 375 | |||
| 376 | if (dssdev->type != OMAP_DISPLAY_TYPE_DPI) | ||
| 377 | continue; | ||
| 378 | |||
| 379 | r = dpi_init_display(dssdev); | ||
| 380 | if (r) { | ||
| 381 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | ||
| 382 | continue; | ||
| 383 | } | ||
| 384 | |||
| 385 | r = omap_dss_register_device(dssdev, &pdev->dev, i); | ||
| 386 | if (r) | ||
| 387 | DSSERR("device %s register failed: %d\n", | ||
| 388 | dssdev->name, r); | ||
| 389 | } | ||
| 390 | } | ||
| 391 | |||
| 392 | static int __init omap_dpi_probe(struct platform_device *pdev) | ||
| 393 | { | ||
| 394 | dpi_probe_pdata(pdev); | ||
| 395 | |||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | static int __exit omap_dpi_remove(struct platform_device *pdev) | ||
| 400 | { | ||
| 401 | omap_dss_unregister_child_devices(&pdev->dev); | ||
| 402 | |||
| 383 | return 0; | 403 | return 0; |
| 384 | } | 404 | } |
| 385 | 405 | ||
| 386 | void dpi_exit(void) | 406 | static struct platform_driver omap_dpi_driver = { |
| 407 | .remove = __exit_p(omap_dpi_remove), | ||
| 408 | .driver = { | ||
| 409 | .name = "omapdss_dpi", | ||
| 410 | .owner = THIS_MODULE, | ||
| 411 | }, | ||
| 412 | }; | ||
| 413 | |||
| 414 | int __init dpi_init_platform_driver(void) | ||
| 387 | { | 415 | { |
| 416 | return platform_driver_probe(&omap_dpi_driver, omap_dpi_probe); | ||
| 388 | } | 417 | } |
| 389 | 418 | ||
| 419 | void __exit dpi_uninit_platform_driver(void) | ||
| 420 | { | ||
| 421 | platform_driver_unregister(&omap_dpi_driver); | ||
| 422 | } | ||
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 210a3c4f6150..ec363d8390ed 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
| @@ -256,14 +256,13 @@ struct dsi_data { | |||
| 256 | struct platform_device *pdev; | 256 | struct platform_device *pdev; |
| 257 | void __iomem *base; | 257 | void __iomem *base; |
| 258 | 258 | ||
| 259 | int module_id; | ||
| 260 | |||
| 259 | int irq; | 261 | int irq; |
| 260 | 262 | ||
| 261 | struct clk *dss_clk; | 263 | struct clk *dss_clk; |
| 262 | struct clk *sys_clk; | 264 | struct clk *sys_clk; |
| 263 | 265 | ||
| 264 | int (*enable_pads)(int dsi_id, unsigned lane_mask); | ||
| 265 | void (*disable_pads)(int dsi_id, unsigned lane_mask); | ||
| 266 | |||
| 267 | struct dsi_clock_info current_cinfo; | 266 | struct dsi_clock_info current_cinfo; |
| 268 | 267 | ||
| 269 | bool vdds_dsi_enabled; | 268 | bool vdds_dsi_enabled; |
| @@ -361,11 +360,6 @@ struct platform_device *dsi_get_dsidev_from_id(int module) | |||
| 361 | return dsi_pdev_map[module]; | 360 | return dsi_pdev_map[module]; |
| 362 | } | 361 | } |
| 363 | 362 | ||
| 364 | static inline int dsi_get_dsidev_id(struct platform_device *dsidev) | ||
| 365 | { | ||
| 366 | return dsidev->id; | ||
| 367 | } | ||
| 368 | |||
| 369 | static inline void dsi_write_reg(struct platform_device *dsidev, | 363 | static inline void dsi_write_reg(struct platform_device *dsidev, |
| 370 | const struct dsi_reg idx, u32 val) | 364 | const struct dsi_reg idx, u32 val) |
| 371 | { | 365 | { |
| @@ -452,6 +446,7 @@ u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) | |||
| 452 | return 16; | 446 | return 16; |
| 453 | default: | 447 | default: |
| 454 | BUG(); | 448 | BUG(); |
| 449 | return 0; | ||
| 455 | } | 450 | } |
| 456 | } | 451 | } |
| 457 | 452 | ||
| @@ -1184,10 +1179,9 @@ static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev) | |||
| 1184 | static unsigned long dsi_fclk_rate(struct platform_device *dsidev) | 1179 | static unsigned long dsi_fclk_rate(struct platform_device *dsidev) |
| 1185 | { | 1180 | { |
| 1186 | unsigned long r; | 1181 | unsigned long r; |
| 1187 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
| 1188 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 1182 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 1189 | 1183 | ||
| 1190 | if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) { | 1184 | if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) { |
| 1191 | /* DSI FCLK source is DSS_CLK_FCK */ | 1185 | /* DSI FCLK source is DSS_CLK_FCK */ |
| 1192 | r = clk_get_rate(dsi->dss_clk); | 1186 | r = clk_get_rate(dsi->dss_clk); |
| 1193 | } else { | 1187 | } else { |
| @@ -1279,10 +1273,9 @@ static int dsi_pll_power(struct platform_device *dsidev, | |||
| 1279 | } | 1273 | } |
| 1280 | 1274 | ||
| 1281 | /* calculate clock rates using dividers in cinfo */ | 1275 | /* calculate clock rates using dividers in cinfo */ |
| 1282 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | 1276 | static int dsi_calc_clock_rates(struct platform_device *dsidev, |
| 1283 | struct dsi_clock_info *cinfo) | 1277 | struct dsi_clock_info *cinfo) |
| 1284 | { | 1278 | { |
| 1285 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
| 1286 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 1279 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 1287 | 1280 | ||
| 1288 | if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max) | 1281 | if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max) |
| @@ -1297,21 +1290,8 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
| 1297 | if (cinfo->regm_dsi > dsi->regm_dsi_max) | 1290 | if (cinfo->regm_dsi > dsi->regm_dsi_max) |
| 1298 | return -EINVAL; | 1291 | return -EINVAL; |
| 1299 | 1292 | ||
| 1300 | if (cinfo->use_sys_clk) { | 1293 | cinfo->clkin = clk_get_rate(dsi->sys_clk); |
| 1301 | cinfo->clkin = clk_get_rate(dsi->sys_clk); | 1294 | cinfo->fint = cinfo->clkin / cinfo->regn; |
| 1302 | /* XXX it is unclear if highfreq should be used | ||
| 1303 | * with DSS_SYS_CLK source also */ | ||
| 1304 | cinfo->highfreq = 0; | ||
| 1305 | } else { | ||
| 1306 | cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id); | ||
| 1307 | |||
| 1308 | if (cinfo->clkin < 32000000) | ||
| 1309 | cinfo->highfreq = 0; | ||
| 1310 | else | ||
| 1311 | cinfo->highfreq = 1; | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); | ||
| 1315 | 1295 | ||
| 1316 | if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min) | 1296 | if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min) |
| 1317 | return -EINVAL; | 1297 | return -EINVAL; |
| @@ -1378,27 +1358,21 @@ retry: | |||
| 1378 | 1358 | ||
| 1379 | memset(&cur, 0, sizeof(cur)); | 1359 | memset(&cur, 0, sizeof(cur)); |
| 1380 | cur.clkin = dss_sys_clk; | 1360 | cur.clkin = dss_sys_clk; |
| 1381 | cur.use_sys_clk = 1; | ||
| 1382 | cur.highfreq = 0; | ||
| 1383 | 1361 | ||
| 1384 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ | 1362 | /* 0.75MHz < Fint = clkin / regn < 2.1MHz */ |
| 1385 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ | ||
| 1386 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ | 1363 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ |
| 1387 | for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { | 1364 | for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { |
| 1388 | if (cur.highfreq == 0) | 1365 | cur.fint = cur.clkin / cur.regn; |
| 1389 | cur.fint = cur.clkin / cur.regn; | ||
| 1390 | else | ||
| 1391 | cur.fint = cur.clkin / (2 * cur.regn); | ||
| 1392 | 1366 | ||
| 1393 | if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) | 1367 | if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) |
| 1394 | continue; | 1368 | continue; |
| 1395 | 1369 | ||
| 1396 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ | 1370 | /* DSIPHY(MHz) = (2 * regm / regn) * clkin */ |
| 1397 | for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { | 1371 | for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { |
| 1398 | unsigned long a, b; | 1372 | unsigned long a, b; |
| 1399 | 1373 | ||
| 1400 | a = 2 * cur.regm * (cur.clkin/1000); | 1374 | a = 2 * cur.regm * (cur.clkin/1000); |
| 1401 | b = cur.regn * (cur.highfreq + 1); | 1375 | b = cur.regn; |
| 1402 | cur.clkin4ddr = a / b * 1000; | 1376 | cur.clkin4ddr = a / b * 1000; |
| 1403 | 1377 | ||
| 1404 | if (cur.clkin4ddr > 1800 * 1000 * 1000) | 1378 | if (cur.clkin4ddr > 1800 * 1000 * 1000) |
| @@ -1486,9 +1460,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, | |||
| 1486 | 1460 | ||
| 1487 | DSSDBGF(); | 1461 | DSSDBGF(); |
| 1488 | 1462 | ||
| 1489 | dsi->current_cinfo.use_sys_clk = cinfo->use_sys_clk; | 1463 | dsi->current_cinfo.clkin = cinfo->clkin; |
| 1490 | dsi->current_cinfo.highfreq = cinfo->highfreq; | ||
| 1491 | |||
| 1492 | dsi->current_cinfo.fint = cinfo->fint; | 1464 | dsi->current_cinfo.fint = cinfo->fint; |
| 1493 | dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr; | 1465 | dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr; |
| 1494 | dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk = | 1466 | dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk = |
| @@ -1503,17 +1475,13 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, | |||
| 1503 | 1475 | ||
| 1504 | DSSDBG("DSI Fint %ld\n", cinfo->fint); | 1476 | DSSDBG("DSI Fint %ld\n", cinfo->fint); |
| 1505 | 1477 | ||
| 1506 | DSSDBG("clkin (%s) rate %ld, highfreq %d\n", | 1478 | DSSDBG("clkin rate %ld\n", cinfo->clkin); |
| 1507 | cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree", | ||
| 1508 | cinfo->clkin, | ||
| 1509 | cinfo->highfreq); | ||
| 1510 | 1479 | ||
| 1511 | /* DSIPHY == CLKIN4DDR */ | 1480 | /* DSIPHY == CLKIN4DDR */ |
| 1512 | DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n", | 1481 | DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n", |
| 1513 | cinfo->regm, | 1482 | cinfo->regm, |
| 1514 | cinfo->regn, | 1483 | cinfo->regn, |
| 1515 | cinfo->clkin, | 1484 | cinfo->clkin, |
| 1516 | cinfo->highfreq + 1, | ||
| 1517 | cinfo->clkin4ddr); | 1485 | cinfo->clkin4ddr); |
| 1518 | 1486 | ||
| 1519 | DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", | 1487 | DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", |
| @@ -1568,10 +1536,6 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, | |||
| 1568 | 1536 | ||
| 1569 | if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) | 1537 | if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) |
| 1570 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ | 1538 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ |
| 1571 | l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, | ||
| 1572 | 11, 11); /* DSI_PLL_CLKSEL */ | ||
| 1573 | l = FLD_MOD(l, cinfo->highfreq, | ||
| 1574 | 12, 12); /* DSI_PLL_HIGHFREQ */ | ||
| 1575 | l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ | 1539 | l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ |
| 1576 | l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ | 1540 | l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ |
| 1577 | l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ | 1541 | l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ |
| @@ -1716,7 +1680,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, | |||
| 1716 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 1680 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 1717 | struct dsi_clock_info *cinfo = &dsi->current_cinfo; | 1681 | struct dsi_clock_info *cinfo = &dsi->current_cinfo; |
| 1718 | enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; | 1682 | enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; |
| 1719 | int dsi_module = dsi_get_dsidev_id(dsidev); | 1683 | int dsi_module = dsi->module_id; |
| 1720 | 1684 | ||
| 1721 | dispc_clk_src = dss_get_dispc_clk_source(); | 1685 | dispc_clk_src = dss_get_dispc_clk_source(); |
| 1722 | dsi_clk_src = dss_get_dsi_clk_source(dsi_module); | 1686 | dsi_clk_src = dss_get_dsi_clk_source(dsi_module); |
| @@ -1726,8 +1690,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, | |||
| 1726 | 1690 | ||
| 1727 | seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); | 1691 | seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); |
| 1728 | 1692 | ||
| 1729 | seq_printf(s, "dsi pll source = %s\n", | 1693 | seq_printf(s, "dsi pll clkin\t%lu\n", cinfo->clkin); |
| 1730 | cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree"); | ||
| 1731 | 1694 | ||
| 1732 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); | 1695 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); |
| 1733 | 1696 | ||
| @@ -1789,7 +1752,6 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev, | |||
| 1789 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 1752 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 1790 | unsigned long flags; | 1753 | unsigned long flags; |
| 1791 | struct dsi_irq_stats stats; | 1754 | struct dsi_irq_stats stats; |
| 1792 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
| 1793 | 1755 | ||
| 1794 | spin_lock_irqsave(&dsi->irq_stats_lock, flags); | 1756 | spin_lock_irqsave(&dsi->irq_stats_lock, flags); |
| 1795 | 1757 | ||
| @@ -1806,7 +1768,7 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev, | |||
| 1806 | #define PIS(x) \ | 1768 | #define PIS(x) \ |
| 1807 | seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); | 1769 | seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); |
| 1808 | 1770 | ||
| 1809 | seq_printf(s, "-- DSI%d interrupts --\n", dsi_module + 1); | 1771 | seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1); |
| 1810 | PIS(VC0); | 1772 | PIS(VC0); |
| 1811 | PIS(VC1); | 1773 | PIS(VC1); |
| 1812 | PIS(VC2); | 1774 | PIS(VC2); |
| @@ -1886,22 +1848,6 @@ static void dsi2_dump_irqs(struct seq_file *s) | |||
| 1886 | 1848 | ||
| 1887 | dsi_dump_dsidev_irqs(dsidev, s); | 1849 | dsi_dump_dsidev_irqs(dsidev, s); |
| 1888 | } | 1850 | } |
| 1889 | |||
| 1890 | void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir, | ||
| 1891 | const struct file_operations *debug_fops) | ||
| 1892 | { | ||
| 1893 | struct platform_device *dsidev; | ||
| 1894 | |||
| 1895 | dsidev = dsi_get_dsidev_from_id(0); | ||
| 1896 | if (dsidev) | ||
| 1897 | debugfs_create_file("dsi1_irqs", S_IRUGO, debugfs_dir, | ||
| 1898 | &dsi1_dump_irqs, debug_fops); | ||
| 1899 | |||
| 1900 | dsidev = dsi_get_dsidev_from_id(1); | ||
| 1901 | if (dsidev) | ||
| 1902 | debugfs_create_file("dsi2_irqs", S_IRUGO, debugfs_dir, | ||
| 1903 | &dsi2_dump_irqs, debug_fops); | ||
| 1904 | } | ||
| 1905 | #endif | 1851 | #endif |
| 1906 | 1852 | ||
| 1907 | static void dsi_dump_dsidev_regs(struct platform_device *dsidev, | 1853 | static void dsi_dump_dsidev_regs(struct platform_device *dsidev, |
| @@ -2002,21 +1948,6 @@ static void dsi2_dump_regs(struct seq_file *s) | |||
| 2002 | dsi_dump_dsidev_regs(dsidev, s); | 1948 | dsi_dump_dsidev_regs(dsidev, s); |
| 2003 | } | 1949 | } |
| 2004 | 1950 | ||
| 2005 | void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, | ||
| 2006 | const struct file_operations *debug_fops) | ||
| 2007 | { | ||
| 2008 | struct platform_device *dsidev; | ||
| 2009 | |||
| 2010 | dsidev = dsi_get_dsidev_from_id(0); | ||
| 2011 | if (dsidev) | ||
| 2012 | debugfs_create_file("dsi1_regs", S_IRUGO, debugfs_dir, | ||
| 2013 | &dsi1_dump_regs, debug_fops); | ||
| 2014 | |||
| 2015 | dsidev = dsi_get_dsidev_from_id(1); | ||
| 2016 | if (dsidev) | ||
| 2017 | debugfs_create_file("dsi2_regs", S_IRUGO, debugfs_dir, | ||
| 2018 | &dsi2_dump_regs, debug_fops); | ||
| 2019 | } | ||
| 2020 | enum dsi_cio_power_state { | 1951 | enum dsi_cio_power_state { |
| 2021 | DSI_COMPLEXIO_POWER_OFF = 0x0, | 1952 | DSI_COMPLEXIO_POWER_OFF = 0x0, |
| 2022 | DSI_COMPLEXIO_POWER_ON = 0x1, | 1953 | DSI_COMPLEXIO_POWER_ON = 0x1, |
| @@ -2073,6 +2004,7 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) | |||
| 2073 | return 1365 * 3; /* 1365x24 bits */ | 2004 | return 1365 * 3; /* 1365x24 bits */ |
| 2074 | default: | 2005 | default: |
| 2075 | BUG(); | 2006 | BUG(); |
| 2007 | return 0; | ||
| 2076 | } | 2008 | } |
| 2077 | } | 2009 | } |
| 2078 | 2010 | ||
| @@ -2337,7 +2269,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) | |||
| 2337 | 2269 | ||
| 2338 | DSSDBGF(); | 2270 | DSSDBGF(); |
| 2339 | 2271 | ||
| 2340 | r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); | 2272 | r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); |
| 2341 | if (r) | 2273 | if (r) |
| 2342 | return r; | 2274 | return r; |
| 2343 | 2275 | ||
| @@ -2447,7 +2379,7 @@ err_cio_pwr: | |||
| 2447 | dsi_cio_disable_lane_override(dsidev); | 2379 | dsi_cio_disable_lane_override(dsidev); |
| 2448 | err_scp_clk_dom: | 2380 | err_scp_clk_dom: |
| 2449 | dsi_disable_scp_clk(dsidev); | 2381 | dsi_disable_scp_clk(dsidev); |
| 2450 | dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); | 2382 | dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); |
| 2451 | return r; | 2383 | return r; |
| 2452 | } | 2384 | } |
| 2453 | 2385 | ||
| @@ -2461,7 +2393,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev) | |||
| 2461 | 2393 | ||
| 2462 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); | 2394 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); |
| 2463 | dsi_disable_scp_clk(dsidev); | 2395 | dsi_disable_scp_clk(dsidev); |
| 2464 | dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); | 2396 | dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); |
| 2465 | } | 2397 | } |
| 2466 | 2398 | ||
| 2467 | static void dsi_config_tx_fifo(struct platform_device *dsidev, | 2399 | static void dsi_config_tx_fifo(struct platform_device *dsidev, |
| @@ -2485,6 +2417,7 @@ static void dsi_config_tx_fifo(struct platform_device *dsidev, | |||
| 2485 | if (add + size > 4) { | 2417 | if (add + size > 4) { |
| 2486 | DSSERR("Illegal FIFO configuration\n"); | 2418 | DSSERR("Illegal FIFO configuration\n"); |
| 2487 | BUG(); | 2419 | BUG(); |
| 2420 | return; | ||
| 2488 | } | 2421 | } |
| 2489 | 2422 | ||
| 2490 | v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); | 2423 | v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); |
| @@ -2517,6 +2450,7 @@ static void dsi_config_rx_fifo(struct platform_device *dsidev, | |||
| 2517 | if (add + size > 4) { | 2450 | if (add + size > 4) { |
| 2518 | DSSERR("Illegal FIFO configuration\n"); | 2451 | DSSERR("Illegal FIFO configuration\n"); |
| 2519 | BUG(); | 2452 | BUG(); |
| 2453 | return; | ||
| 2520 | } | 2454 | } |
| 2521 | 2455 | ||
| 2522 | v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); | 2456 | v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); |
| @@ -2658,6 +2592,7 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel) | |||
| 2658 | return dsi_sync_vc_l4(dsidev, channel); | 2592 | return dsi_sync_vc_l4(dsidev, channel); |
| 2659 | default: | 2593 | default: |
| 2660 | BUG(); | 2594 | BUG(); |
| 2595 | return -EINVAL; | ||
| 2661 | } | 2596 | } |
| 2662 | } | 2597 | } |
| 2663 | 2598 | ||
| @@ -3226,6 +3161,7 @@ static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, | |||
| 3226 | data = reqdata[0] | (reqdata[1] << 8); | 3161 | data = reqdata[0] | (reqdata[1] << 8); |
| 3227 | } else { | 3162 | } else { |
| 3228 | BUG(); | 3163 | BUG(); |
| 3164 | return -EINVAL; | ||
| 3229 | } | 3165 | } |
| 3230 | 3166 | ||
| 3231 | r = dsi_vc_send_short(dsidev, channel, data_type, data, 0); | 3167 | r = dsi_vc_send_short(dsidev, channel, data_type, data, 0); |
| @@ -3340,7 +3276,6 @@ static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel, | |||
| 3340 | goto err; | 3276 | goto err; |
| 3341 | } | 3277 | } |
| 3342 | 3278 | ||
| 3343 | BUG(); | ||
| 3344 | err: | 3279 | err: |
| 3345 | DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel, | 3280 | DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel, |
| 3346 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS"); | 3281 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS"); |
| @@ -3735,6 +3670,186 @@ static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) | |||
| 3735 | dsi_write_reg(dsidev, DSI_CTRL, r); | 3670 | dsi_write_reg(dsidev, DSI_CTRL, r); |
| 3736 | } | 3671 | } |
| 3737 | 3672 | ||
| 3673 | /* | ||
| 3674 | * According to section 'HS Command Mode Interleaving' in OMAP TRM, Scenario 3 | ||
| 3675 | * results in maximum transition time for data and clock lanes to enter and | ||
| 3676 | * exit HS mode. Hence, this is the scenario where the least amount of command | ||
| 3677 | * mode data can be interleaved. We program the minimum amount of TXBYTECLKHS | ||
| 3678 | * clock cycles that can be used to interleave command mode data in HS so that | ||
| 3679 | * all scenarios are satisfied. | ||
| 3680 | */ | ||
| 3681 | static int dsi_compute_interleave_hs(int blank, bool ddr_alwon, int enter_hs, | ||
| 3682 | int exit_hs, int exiths_clk, int ddr_pre, int ddr_post) | ||
| 3683 | { | ||
| 3684 | int transition; | ||
| 3685 | |||
| 3686 | /* | ||
| 3687 | * If DDR_CLK_ALWAYS_ON is set, we need to consider HS mode transition | ||
| 3688 | * time of data lanes only, if it isn't set, we need to consider HS | ||
| 3689 | * transition time of both data and clock lanes. HS transition time | ||
| 3690 | * of Scenario 3 is considered. | ||
| 3691 | */ | ||
| 3692 | if (ddr_alwon) { | ||
| 3693 | transition = enter_hs + exit_hs + max(enter_hs, 2) + 1; | ||
| 3694 | } else { | ||
| 3695 | int trans1, trans2; | ||
| 3696 | trans1 = ddr_pre + enter_hs + exit_hs + max(enter_hs, 2) + 1; | ||
| 3697 | trans2 = ddr_pre + enter_hs + exiths_clk + ddr_post + ddr_pre + | ||
| 3698 | enter_hs + 1; | ||
| 3699 | transition = max(trans1, trans2); | ||
| 3700 | } | ||
| 3701 | |||
| 3702 | return blank > transition ? blank - transition : 0; | ||
| 3703 | } | ||
| 3704 | |||
| 3705 | /* | ||
| 3706 | * According to section 'LP Command Mode Interleaving' in OMAP TRM, Scenario 1 | ||
| 3707 | * results in maximum transition time for data lanes to enter and exit LP mode. | ||
| 3708 | * Hence, this is the scenario where the least amount of command mode data can | ||
| 3709 | * be interleaved. We program the minimum amount of bytes that can be | ||
| 3710 | * interleaved in LP so that all scenarios are satisfied. | ||
| 3711 | */ | ||
| 3712 | static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs, | ||
| 3713 | int lp_clk_div, int tdsi_fclk) | ||
| 3714 | { | ||
| 3715 | int trans_lp; /* time required for a LP transition, in TXBYTECLKHS */ | ||
| 3716 | int tlp_avail; /* time left for interleaving commands, in CLKIN4DDR */ | ||
| 3717 | int ttxclkesc; /* period of LP transmit escape clock, in CLKIN4DDR */ | ||
| 3718 | int thsbyte_clk = 16; /* Period of TXBYTECLKHS clock, in CLKIN4DDR */ | ||
| 3719 | int lp_inter; /* cmd mode data that can be interleaved, in bytes */ | ||
| 3720 | |||
| 3721 | /* maximum LP transition time according to Scenario 1 */ | ||
| 3722 | trans_lp = exit_hs + max(enter_hs, 2) + 1; | ||
| 3723 | |||
| 3724 | /* CLKIN4DDR = 16 * TXBYTECLKHS */ | ||
| 3725 | tlp_avail = thsbyte_clk * (blank - trans_lp); | ||
| 3726 | |||
| 3727 | ttxclkesc = tdsi_fclk / lp_clk_div; | ||
| 3728 | |||
| 3729 | lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc - | ||
| 3730 | 26) / 16; | ||
| 3731 | |||
| 3732 | return max(lp_inter, 0); | ||
| 3733 | } | ||
| 3734 | |||
| 3735 | static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev) | ||
| 3736 | { | ||
| 3737 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
| 3738 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
| 3739 | int blanking_mode; | ||
| 3740 | int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode; | ||
| 3741 | int hsa, hfp, hbp, width_bytes, bllp, lp_clk_div; | ||
| 3742 | int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat; | ||
| 3743 | int tclk_trail, ths_exit, exiths_clk; | ||
| 3744 | bool ddr_alwon; | ||
| 3745 | struct omap_video_timings *timings = &dssdev->panel.timings; | ||
| 3746 | int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); | ||
| 3747 | int ndl = dsi->num_lanes_used - 1; | ||
| 3748 | int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1; | ||
| 3749 | int hsa_interleave_hs = 0, hsa_interleave_lp = 0; | ||
| 3750 | int hfp_interleave_hs = 0, hfp_interleave_lp = 0; | ||
| 3751 | int hbp_interleave_hs = 0, hbp_interleave_lp = 0; | ||
| 3752 | int bl_interleave_hs = 0, bl_interleave_lp = 0; | ||
| 3753 | u32 r; | ||
| 3754 | |||
| 3755 | r = dsi_read_reg(dsidev, DSI_CTRL); | ||
| 3756 | blanking_mode = FLD_GET(r, 20, 20); | ||
| 3757 | hfp_blanking_mode = FLD_GET(r, 21, 21); | ||
| 3758 | hbp_blanking_mode = FLD_GET(r, 22, 22); | ||
| 3759 | hsa_blanking_mode = FLD_GET(r, 23, 23); | ||
| 3760 | |||
| 3761 | r = dsi_read_reg(dsidev, DSI_VM_TIMING1); | ||
| 3762 | hbp = FLD_GET(r, 11, 0); | ||
| 3763 | hfp = FLD_GET(r, 23, 12); | ||
| 3764 | hsa = FLD_GET(r, 31, 24); | ||
| 3765 | |||
| 3766 | r = dsi_read_reg(dsidev, DSI_CLK_TIMING); | ||
| 3767 | ddr_clk_post = FLD_GET(r, 7, 0); | ||
| 3768 | ddr_clk_pre = FLD_GET(r, 15, 8); | ||
| 3769 | |||
| 3770 | r = dsi_read_reg(dsidev, DSI_VM_TIMING7); | ||
| 3771 | exit_hs_mode_lat = FLD_GET(r, 15, 0); | ||
| 3772 | enter_hs_mode_lat = FLD_GET(r, 31, 16); | ||
| 3773 | |||
| 3774 | r = dsi_read_reg(dsidev, DSI_CLK_CTRL); | ||
| 3775 | lp_clk_div = FLD_GET(r, 12, 0); | ||
| 3776 | ddr_alwon = FLD_GET(r, 13, 13); | ||
| 3777 | |||
| 3778 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); | ||
| 3779 | ths_exit = FLD_GET(r, 7, 0); | ||
| 3780 | |||
| 3781 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); | ||
| 3782 | tclk_trail = FLD_GET(r, 15, 8); | ||
| 3783 | |||
| 3784 | exiths_clk = ths_exit + tclk_trail; | ||
| 3785 | |||
| 3786 | width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8); | ||
| 3787 | bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl); | ||
| 3788 | |||
| 3789 | if (!hsa_blanking_mode) { | ||
| 3790 | hsa_interleave_hs = dsi_compute_interleave_hs(hsa, ddr_alwon, | ||
| 3791 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
| 3792 | exiths_clk, ddr_clk_pre, ddr_clk_post); | ||
| 3793 | hsa_interleave_lp = dsi_compute_interleave_lp(hsa, | ||
| 3794 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
| 3795 | lp_clk_div, dsi_fclk_hsdiv); | ||
| 3796 | } | ||
| 3797 | |||
| 3798 | if (!hfp_blanking_mode) { | ||
| 3799 | hfp_interleave_hs = dsi_compute_interleave_hs(hfp, ddr_alwon, | ||
| 3800 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
| 3801 | exiths_clk, ddr_clk_pre, ddr_clk_post); | ||
| 3802 | hfp_interleave_lp = dsi_compute_interleave_lp(hfp, | ||
| 3803 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
| 3804 | lp_clk_div, dsi_fclk_hsdiv); | ||
| 3805 | } | ||
| 3806 | |||
| 3807 | if (!hbp_blanking_mode) { | ||
| 3808 | hbp_interleave_hs = dsi_compute_interleave_hs(hbp, ddr_alwon, | ||
| 3809 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
| 3810 | exiths_clk, ddr_clk_pre, ddr_clk_post); | ||
| 3811 | |||
| 3812 | hbp_interleave_lp = dsi_compute_interleave_lp(hbp, | ||
| 3813 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
| 3814 | lp_clk_div, dsi_fclk_hsdiv); | ||
| 3815 | } | ||
| 3816 | |||
| 3817 | if (!blanking_mode) { | ||
| 3818 | bl_interleave_hs = dsi_compute_interleave_hs(bllp, ddr_alwon, | ||
| 3819 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
| 3820 | exiths_clk, ddr_clk_pre, ddr_clk_post); | ||
| 3821 | |||
| 3822 | bl_interleave_lp = dsi_compute_interleave_lp(bllp, | ||
| 3823 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
| 3824 | lp_clk_div, dsi_fclk_hsdiv); | ||
| 3825 | } | ||
| 3826 | |||
| 3827 | DSSDBG("DSI HS interleaving(TXBYTECLKHS) HSA %d, HFP %d, HBP %d, BLLP %d\n", | ||
| 3828 | hsa_interleave_hs, hfp_interleave_hs, hbp_interleave_hs, | ||
| 3829 | bl_interleave_hs); | ||
| 3830 | |||
| 3831 | DSSDBG("DSI LP interleaving(bytes) HSA %d, HFP %d, HBP %d, BLLP %d\n", | ||
| 3832 | hsa_interleave_lp, hfp_interleave_lp, hbp_interleave_lp, | ||
| 3833 | bl_interleave_lp); | ||
| 3834 | |||
| 3835 | r = dsi_read_reg(dsidev, DSI_VM_TIMING4); | ||
| 3836 | r = FLD_MOD(r, hsa_interleave_hs, 23, 16); | ||
| 3837 | r = FLD_MOD(r, hfp_interleave_hs, 15, 8); | ||
| 3838 | r = FLD_MOD(r, hbp_interleave_hs, 7, 0); | ||
| 3839 | dsi_write_reg(dsidev, DSI_VM_TIMING4, r); | ||
| 3840 | |||
| 3841 | r = dsi_read_reg(dsidev, DSI_VM_TIMING5); | ||
| 3842 | r = FLD_MOD(r, hsa_interleave_lp, 23, 16); | ||
| 3843 | r = FLD_MOD(r, hfp_interleave_lp, 15, 8); | ||
| 3844 | r = FLD_MOD(r, hbp_interleave_lp, 7, 0); | ||
| 3845 | dsi_write_reg(dsidev, DSI_VM_TIMING5, r); | ||
| 3846 | |||
| 3847 | r = dsi_read_reg(dsidev, DSI_VM_TIMING6); | ||
| 3848 | r = FLD_MOD(r, bl_interleave_hs, 31, 15); | ||
| 3849 | r = FLD_MOD(r, bl_interleave_lp, 16, 0); | ||
| 3850 | dsi_write_reg(dsidev, DSI_VM_TIMING6, r); | ||
| 3851 | } | ||
| 3852 | |||
| 3738 | static int dsi_proto_config(struct omap_dss_device *dssdev) | 3853 | static int dsi_proto_config(struct omap_dss_device *dssdev) |
| 3739 | { | 3854 | { |
| 3740 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3855 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| @@ -3769,6 +3884,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
| 3769 | break; | 3884 | break; |
| 3770 | default: | 3885 | default: |
| 3771 | BUG(); | 3886 | BUG(); |
| 3887 | return -EINVAL; | ||
| 3772 | } | 3888 | } |
| 3773 | 3889 | ||
| 3774 | r = dsi_read_reg(dsidev, DSI_CTRL); | 3890 | r = dsi_read_reg(dsidev, DSI_CTRL); |
| @@ -3793,6 +3909,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
| 3793 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { | 3909 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { |
| 3794 | dsi_config_vp_sync_events(dssdev); | 3910 | dsi_config_vp_sync_events(dssdev); |
| 3795 | dsi_config_blanking_modes(dssdev); | 3911 | dsi_config_blanking_modes(dssdev); |
| 3912 | dsi_config_cmd_mode_interleaving(dssdev); | ||
| 3796 | } | 3913 | } |
| 3797 | 3914 | ||
| 3798 | dsi_vc_initial_config(dsidev, 0); | 3915 | dsi_vc_initial_config(dsidev, 0); |
| @@ -4008,6 +4125,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) | |||
| 4008 | break; | 4125 | break; |
| 4009 | default: | 4126 | default: |
| 4010 | BUG(); | 4127 | BUG(); |
| 4128 | return -EINVAL; | ||
| 4011 | }; | 4129 | }; |
| 4012 | 4130 | ||
| 4013 | dsi_if_enable(dsidev, false); | 4131 | dsi_if_enable(dsidev, false); |
| @@ -4192,10 +4310,6 @@ static void dsi_framedone_irq_callback(void *data, u32 mask) | |||
| 4192 | __cancel_delayed_work(&dsi->framedone_timeout_work); | 4310 | __cancel_delayed_work(&dsi->framedone_timeout_work); |
| 4193 | 4311 | ||
| 4194 | dsi_handle_framedone(dsidev, 0); | 4312 | dsi_handle_framedone(dsidev, 0); |
| 4195 | |||
| 4196 | #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC | ||
| 4197 | dispc_fake_vsync_irq(); | ||
| 4198 | #endif | ||
| 4199 | } | 4313 | } |
| 4200 | 4314 | ||
| 4201 | int omap_dsi_update(struct omap_dss_device *dssdev, int channel, | 4315 | int omap_dsi_update(struct omap_dss_device *dssdev, int channel, |
| @@ -4259,13 +4373,12 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | |||
| 4259 | dispc_mgr_enable_stallmode(dssdev->manager->id, true); | 4373 | dispc_mgr_enable_stallmode(dssdev->manager->id, true); |
| 4260 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); | 4374 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); |
| 4261 | 4375 | ||
| 4262 | dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings); | 4376 | dss_mgr_set_timings(dssdev->manager, &timings); |
| 4263 | } else { | 4377 | } else { |
| 4264 | dispc_mgr_enable_stallmode(dssdev->manager->id, false); | 4378 | dispc_mgr_enable_stallmode(dssdev->manager->id, false); |
| 4265 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); | 4379 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); |
| 4266 | 4380 | ||
| 4267 | dispc_mgr_set_lcd_timings(dssdev->manager->id, | 4381 | dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); |
| 4268 | &dssdev->panel.timings); | ||
| 4269 | } | 4382 | } |
| 4270 | 4383 | ||
| 4271 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, | 4384 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, |
| @@ -4294,13 +4407,11 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | |||
| 4294 | struct dsi_clock_info cinfo; | 4407 | struct dsi_clock_info cinfo; |
| 4295 | int r; | 4408 | int r; |
| 4296 | 4409 | ||
| 4297 | /* we always use DSS_CLK_SYSCK as input clock */ | ||
| 4298 | cinfo.use_sys_clk = true; | ||
| 4299 | cinfo.regn = dssdev->clocks.dsi.regn; | 4410 | cinfo.regn = dssdev->clocks.dsi.regn; |
| 4300 | cinfo.regm = dssdev->clocks.dsi.regm; | 4411 | cinfo.regm = dssdev->clocks.dsi.regm; |
| 4301 | cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; | 4412 | cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; |
| 4302 | cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; | 4413 | cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; |
| 4303 | r = dsi_calc_clock_rates(dssdev, &cinfo); | 4414 | r = dsi_calc_clock_rates(dsidev, &cinfo); |
| 4304 | if (r) { | 4415 | if (r) { |
| 4305 | DSSERR("Failed to calc dsi clocks\n"); | 4416 | DSSERR("Failed to calc dsi clocks\n"); |
| 4306 | return r; | 4417 | return r; |
| @@ -4345,7 +4456,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
| 4345 | static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | 4456 | static int dsi_display_init_dsi(struct omap_dss_device *dssdev) |
| 4346 | { | 4457 | { |
| 4347 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4458 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| 4348 | int dsi_module = dsi_get_dsidev_id(dsidev); | 4459 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 4349 | int r; | 4460 | int r; |
| 4350 | 4461 | ||
| 4351 | r = dsi_pll_init(dsidev, true, true); | 4462 | r = dsi_pll_init(dsidev, true, true); |
| @@ -4357,7 +4468,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
| 4357 | goto err1; | 4468 | goto err1; |
| 4358 | 4469 | ||
| 4359 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); | 4470 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); |
| 4360 | dss_select_dsi_clk_source(dsi_module, dssdev->clocks.dsi.dsi_fclk_src); | 4471 | dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); |
| 4361 | dss_select_lcd_clk_source(dssdev->manager->id, | 4472 | dss_select_lcd_clk_source(dssdev->manager->id, |
| 4362 | dssdev->clocks.dispc.channel.lcd_clk_src); | 4473 | dssdev->clocks.dispc.channel.lcd_clk_src); |
| 4363 | 4474 | ||
| @@ -4396,7 +4507,7 @@ err3: | |||
| 4396 | dsi_cio_uninit(dssdev); | 4507 | dsi_cio_uninit(dssdev); |
| 4397 | err2: | 4508 | err2: |
| 4398 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | 4509 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
| 4399 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); | 4510 | dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); |
| 4400 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); | 4511 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); |
| 4401 | 4512 | ||
| 4402 | err1: | 4513 | err1: |
| @@ -4410,7 +4521,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, | |||
| 4410 | { | 4521 | { |
| 4411 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4522 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| 4412 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4523 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 4413 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
| 4414 | 4524 | ||
| 4415 | if (enter_ulps && !dsi->ulps_enabled) | 4525 | if (enter_ulps && !dsi->ulps_enabled) |
| 4416 | dsi_enter_ulps(dsidev); | 4526 | dsi_enter_ulps(dsidev); |
| @@ -4423,7 +4533,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, | |||
| 4423 | dsi_vc_enable(dsidev, 3, 0); | 4533 | dsi_vc_enable(dsidev, 3, 0); |
| 4424 | 4534 | ||
| 4425 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | 4535 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
| 4426 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); | 4536 | dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); |
| 4427 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); | 4537 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); |
| 4428 | dsi_cio_uninit(dssdev); | 4538 | dsi_cio_uninit(dssdev); |
| 4429 | dsi_pll_uninit(dsidev, disconnect_lanes); | 4539 | dsi_pll_uninit(dsidev, disconnect_lanes); |
| @@ -4527,7 +4637,7 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
| 4527 | } | 4637 | } |
| 4528 | EXPORT_SYMBOL(omapdss_dsi_enable_te); | 4638 | EXPORT_SYMBOL(omapdss_dsi_enable_te); |
| 4529 | 4639 | ||
| 4530 | int dsi_init_display(struct omap_dss_device *dssdev) | 4640 | static int __init dsi_init_display(struct omap_dss_device *dssdev) |
| 4531 | { | 4641 | { |
| 4532 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4642 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| 4533 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4643 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| @@ -4680,13 +4790,39 @@ static void dsi_put_clocks(struct platform_device *dsidev) | |||
| 4680 | clk_put(dsi->sys_clk); | 4790 | clk_put(dsi->sys_clk); |
| 4681 | } | 4791 | } |
| 4682 | 4792 | ||
| 4793 | static void __init dsi_probe_pdata(struct platform_device *dsidev) | ||
| 4794 | { | ||
| 4795 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
| 4796 | struct omap_dss_board_info *pdata = dsidev->dev.platform_data; | ||
| 4797 | int i, r; | ||
| 4798 | |||
| 4799 | for (i = 0; i < pdata->num_devices; ++i) { | ||
| 4800 | struct omap_dss_device *dssdev = pdata->devices[i]; | ||
| 4801 | |||
| 4802 | if (dssdev->type != OMAP_DISPLAY_TYPE_DSI) | ||
| 4803 | continue; | ||
| 4804 | |||
| 4805 | if (dssdev->phy.dsi.module != dsi->module_id) | ||
| 4806 | continue; | ||
| 4807 | |||
| 4808 | r = dsi_init_display(dssdev); | ||
| 4809 | if (r) { | ||
| 4810 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | ||
| 4811 | continue; | ||
| 4812 | } | ||
| 4813 | |||
| 4814 | r = omap_dss_register_device(dssdev, &dsidev->dev, i); | ||
| 4815 | if (r) | ||
| 4816 | DSSERR("device %s register failed: %d\n", | ||
| 4817 | dssdev->name, r); | ||
| 4818 | } | ||
| 4819 | } | ||
| 4820 | |||
| 4683 | /* DSI1 HW IP initialisation */ | 4821 | /* DSI1 HW IP initialisation */ |
| 4684 | static int omap_dsihw_probe(struct platform_device *dsidev) | 4822 | static int __init omap_dsihw_probe(struct platform_device *dsidev) |
| 4685 | { | 4823 | { |
| 4686 | struct omap_display_platform_data *dss_plat_data; | ||
| 4687 | struct omap_dss_board_info *board_info; | ||
| 4688 | u32 rev; | 4824 | u32 rev; |
| 4689 | int r, i, dsi_module = dsi_get_dsidev_id(dsidev); | 4825 | int r, i; |
| 4690 | struct resource *dsi_mem; | 4826 | struct resource *dsi_mem; |
| 4691 | struct dsi_data *dsi; | 4827 | struct dsi_data *dsi; |
| 4692 | 4828 | ||
| @@ -4694,15 +4830,11 @@ static int omap_dsihw_probe(struct platform_device *dsidev) | |||
| 4694 | if (!dsi) | 4830 | if (!dsi) |
| 4695 | return -ENOMEM; | 4831 | return -ENOMEM; |
| 4696 | 4832 | ||
| 4833 | dsi->module_id = dsidev->id; | ||
| 4697 | dsi->pdev = dsidev; | 4834 | dsi->pdev = dsidev; |
| 4698 | dsi_pdev_map[dsi_module] = dsidev; | 4835 | dsi_pdev_map[dsi->module_id] = dsidev; |
| 4699 | dev_set_drvdata(&dsidev->dev, dsi); | 4836 | dev_set_drvdata(&dsidev->dev, dsi); |
| 4700 | 4837 | ||
| 4701 | dss_plat_data = dsidev->dev.platform_data; | ||
| 4702 | board_info = dss_plat_data->board_data; | ||
| 4703 | dsi->enable_pads = board_info->dsi_enable_pads; | ||
| 4704 | dsi->disable_pads = board_info->dsi_disable_pads; | ||
| 4705 | |||
| 4706 | spin_lock_init(&dsi->irq_lock); | 4838 | spin_lock_init(&dsi->irq_lock); |
| 4707 | spin_lock_init(&dsi->errors_lock); | 4839 | spin_lock_init(&dsi->errors_lock); |
| 4708 | dsi->errors = 0; | 4840 | dsi->errors = 0; |
| @@ -4780,8 +4912,21 @@ static int omap_dsihw_probe(struct platform_device *dsidev) | |||
| 4780 | else | 4912 | else |
| 4781 | dsi->num_lanes_supported = 3; | 4913 | dsi->num_lanes_supported = 3; |
| 4782 | 4914 | ||
| 4915 | dsi_probe_pdata(dsidev); | ||
| 4916 | |||
| 4783 | dsi_runtime_put(dsidev); | 4917 | dsi_runtime_put(dsidev); |
| 4784 | 4918 | ||
| 4919 | if (dsi->module_id == 0) | ||
| 4920 | dss_debugfs_create_file("dsi1_regs", dsi1_dump_regs); | ||
| 4921 | else if (dsi->module_id == 1) | ||
| 4922 | dss_debugfs_create_file("dsi2_regs", dsi2_dump_regs); | ||
| 4923 | |||
| 4924 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
| 4925 | if (dsi->module_id == 0) | ||
| 4926 | dss_debugfs_create_file("dsi1_irqs", dsi1_dump_irqs); | ||
| 4927 | else if (dsi->module_id == 1) | ||
| 4928 | dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs); | ||
| 4929 | #endif | ||
| 4785 | return 0; | 4930 | return 0; |
| 4786 | 4931 | ||
| 4787 | err_runtime_get: | 4932 | err_runtime_get: |
| @@ -4790,12 +4935,14 @@ err_runtime_get: | |||
| 4790 | return r; | 4935 | return r; |
| 4791 | } | 4936 | } |
| 4792 | 4937 | ||
| 4793 | static int omap_dsihw_remove(struct platform_device *dsidev) | 4938 | static int __exit omap_dsihw_remove(struct platform_device *dsidev) |
| 4794 | { | 4939 | { |
| 4795 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4940 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 4796 | 4941 | ||
| 4797 | WARN_ON(dsi->scp_clk_refcount > 0); | 4942 | WARN_ON(dsi->scp_clk_refcount > 0); |
| 4798 | 4943 | ||
| 4944 | omap_dss_unregister_child_devices(&dsidev->dev); | ||
| 4945 | |||
| 4799 | pm_runtime_disable(&dsidev->dev); | 4946 | pm_runtime_disable(&dsidev->dev); |
| 4800 | 4947 | ||
| 4801 | dsi_put_clocks(dsidev); | 4948 | dsi_put_clocks(dsidev); |
| @@ -4816,7 +4963,6 @@ static int omap_dsihw_remove(struct platform_device *dsidev) | |||
| 4816 | static int dsi_runtime_suspend(struct device *dev) | 4963 | static int dsi_runtime_suspend(struct device *dev) |
| 4817 | { | 4964 | { |
| 4818 | dispc_runtime_put(); | 4965 | dispc_runtime_put(); |
| 4819 | dss_runtime_put(); | ||
| 4820 | 4966 | ||
| 4821 | return 0; | 4967 | return 0; |
| 4822 | } | 4968 | } |
| @@ -4825,20 +4971,11 @@ static int dsi_runtime_resume(struct device *dev) | |||
| 4825 | { | 4971 | { |
| 4826 | int r; | 4972 | int r; |
| 4827 | 4973 | ||
| 4828 | r = dss_runtime_get(); | ||
| 4829 | if (r) | ||
| 4830 | goto err_get_dss; | ||
| 4831 | |||
| 4832 | r = dispc_runtime_get(); | 4974 | r = dispc_runtime_get(); |
| 4833 | if (r) | 4975 | if (r) |
| 4834 | goto err_get_dispc; | 4976 | return r; |
| 4835 | 4977 | ||
| 4836 | return 0; | 4978 | return 0; |
| 4837 | |||
| 4838 | err_get_dispc: | ||
| 4839 | dss_runtime_put(); | ||
| 4840 | err_get_dss: | ||
| 4841 | return r; | ||
| 4842 | } | 4979 | } |
| 4843 | 4980 | ||
| 4844 | static const struct dev_pm_ops dsi_pm_ops = { | 4981 | static const struct dev_pm_ops dsi_pm_ops = { |
| @@ -4847,8 +4984,7 @@ static const struct dev_pm_ops dsi_pm_ops = { | |||
| 4847 | }; | 4984 | }; |
| 4848 | 4985 | ||
| 4849 | static struct platform_driver omap_dsihw_driver = { | 4986 | static struct platform_driver omap_dsihw_driver = { |
| 4850 | .probe = omap_dsihw_probe, | 4987 | .remove = __exit_p(omap_dsihw_remove), |
| 4851 | .remove = omap_dsihw_remove, | ||
| 4852 | .driver = { | 4988 | .driver = { |
| 4853 | .name = "omapdss_dsi", | 4989 | .name = "omapdss_dsi", |
| 4854 | .owner = THIS_MODULE, | 4990 | .owner = THIS_MODULE, |
| @@ -4856,12 +4992,12 @@ static struct platform_driver omap_dsihw_driver = { | |||
| 4856 | }, | 4992 | }, |
| 4857 | }; | 4993 | }; |
| 4858 | 4994 | ||
| 4859 | int dsi_init_platform_driver(void) | 4995 | int __init dsi_init_platform_driver(void) |
| 4860 | { | 4996 | { |
| 4861 | return platform_driver_register(&omap_dsihw_driver); | 4997 | return platform_driver_probe(&omap_dsihw_driver, omap_dsihw_probe); |
| 4862 | } | 4998 | } |
| 4863 | 4999 | ||
| 4864 | void dsi_uninit_platform_driver(void) | 5000 | void __exit dsi_uninit_platform_driver(void) |
| 4865 | { | 5001 | { |
| 4866 | return platform_driver_unregister(&omap_dsihw_driver); | 5002 | platform_driver_unregister(&omap_dsihw_driver); |
| 4867 | } | 5003 | } |
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index bd2d5e159463..6ea1ff149f6f 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
| @@ -62,6 +62,9 @@ struct dss_reg { | |||
| 62 | #define REG_FLD_MOD(idx, val, start, end) \ | 62 | #define REG_FLD_MOD(idx, val, start, end) \ |
| 63 | dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) | 63 | dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) |
| 64 | 64 | ||
| 65 | static int dss_runtime_get(void); | ||
| 66 | static void dss_runtime_put(void); | ||
| 67 | |||
| 65 | static struct { | 68 | static struct { |
| 66 | struct platform_device *pdev; | 69 | struct platform_device *pdev; |
| 67 | void __iomem *base; | 70 | void __iomem *base; |
| @@ -277,7 +280,7 @@ void dss_dump_clocks(struct seq_file *s) | |||
| 277 | dss_runtime_put(); | 280 | dss_runtime_put(); |
| 278 | } | 281 | } |
| 279 | 282 | ||
| 280 | void dss_dump_regs(struct seq_file *s) | 283 | static void dss_dump_regs(struct seq_file *s) |
| 281 | { | 284 | { |
| 282 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) | 285 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) |
| 283 | 286 | ||
| @@ -322,6 +325,7 @@ void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) | |||
| 322 | break; | 325 | break; |
| 323 | default: | 326 | default: |
| 324 | BUG(); | 327 | BUG(); |
| 328 | return; | ||
| 325 | } | 329 | } |
| 326 | 330 | ||
| 327 | dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end); | 331 | dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end); |
| @@ -335,7 +339,7 @@ void dss_select_dsi_clk_source(int dsi_module, | |||
| 335 | enum omap_dss_clk_source clk_src) | 339 | enum omap_dss_clk_source clk_src) |
| 336 | { | 340 | { |
| 337 | struct platform_device *dsidev; | 341 | struct platform_device *dsidev; |
| 338 | int b; | 342 | int b, pos; |
| 339 | 343 | ||
| 340 | switch (clk_src) { | 344 | switch (clk_src) { |
| 341 | case OMAP_DSS_CLK_SRC_FCK: | 345 | case OMAP_DSS_CLK_SRC_FCK: |
| @@ -355,9 +359,11 @@ void dss_select_dsi_clk_source(int dsi_module, | |||
| 355 | break; | 359 | break; |
| 356 | default: | 360 | default: |
| 357 | BUG(); | 361 | BUG(); |
| 362 | return; | ||
| 358 | } | 363 | } |
| 359 | 364 | ||
| 360 | REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ | 365 | pos = dsi_module == 0 ? 1 : 10; |
| 366 | REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* DSIx_CLK_SWITCH */ | ||
| 361 | 367 | ||
| 362 | dss.dsi_clk_source[dsi_module] = clk_src; | 368 | dss.dsi_clk_source[dsi_module] = clk_src; |
| 363 | } | 369 | } |
| @@ -389,6 +395,7 @@ void dss_select_lcd_clk_source(enum omap_channel channel, | |||
| 389 | break; | 395 | break; |
| 390 | default: | 396 | default: |
| 391 | BUG(); | 397 | BUG(); |
| 398 | return; | ||
| 392 | } | 399 | } |
| 393 | 400 | ||
| 394 | pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12; | 401 | pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12; |
| @@ -706,7 +713,7 @@ static void dss_put_clocks(void) | |||
| 706 | clk_put(dss.dss_clk); | 713 | clk_put(dss.dss_clk); |
| 707 | } | 714 | } |
| 708 | 715 | ||
| 709 | int dss_runtime_get(void) | 716 | static int dss_runtime_get(void) |
| 710 | { | 717 | { |
| 711 | int r; | 718 | int r; |
| 712 | 719 | ||
| @@ -717,7 +724,7 @@ int dss_runtime_get(void) | |||
| 717 | return r < 0 ? r : 0; | 724 | return r < 0 ? r : 0; |
| 718 | } | 725 | } |
| 719 | 726 | ||
| 720 | void dss_runtime_put(void) | 727 | static void dss_runtime_put(void) |
| 721 | { | 728 | { |
| 722 | int r; | 729 | int r; |
| 723 | 730 | ||
| @@ -740,7 +747,7 @@ void dss_debug_dump_clocks(struct seq_file *s) | |||
| 740 | #endif | 747 | #endif |
| 741 | 748 | ||
| 742 | /* DSS HW IP initialisation */ | 749 | /* DSS HW IP initialisation */ |
| 743 | static int omap_dsshw_probe(struct platform_device *pdev) | 750 | static int __init omap_dsshw_probe(struct platform_device *pdev) |
| 744 | { | 751 | { |
| 745 | struct resource *dss_mem; | 752 | struct resource *dss_mem; |
| 746 | u32 rev; | 753 | u32 rev; |
| @@ -785,40 +792,24 @@ static int omap_dsshw_probe(struct platform_device *pdev) | |||
| 785 | dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; | 792 | dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; |
| 786 | dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; | 793 | dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; |
| 787 | 794 | ||
| 788 | r = dpi_init(); | ||
| 789 | if (r) { | ||
| 790 | DSSERR("Failed to initialize DPI\n"); | ||
| 791 | goto err_dpi; | ||
| 792 | } | ||
| 793 | |||
| 794 | r = sdi_init(); | ||
| 795 | if (r) { | ||
| 796 | DSSERR("Failed to initialize SDI\n"); | ||
| 797 | goto err_sdi; | ||
| 798 | } | ||
| 799 | |||
| 800 | rev = dss_read_reg(DSS_REVISION); | 795 | rev = dss_read_reg(DSS_REVISION); |
| 801 | printk(KERN_INFO "OMAP DSS rev %d.%d\n", | 796 | printk(KERN_INFO "OMAP DSS rev %d.%d\n", |
| 802 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | 797 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
| 803 | 798 | ||
| 804 | dss_runtime_put(); | 799 | dss_runtime_put(); |
| 805 | 800 | ||
| 801 | dss_debugfs_create_file("dss", dss_dump_regs); | ||
| 802 | |||
| 806 | return 0; | 803 | return 0; |
| 807 | err_sdi: | 804 | |
| 808 | dpi_exit(); | ||
| 809 | err_dpi: | ||
| 810 | dss_runtime_put(); | ||
| 811 | err_runtime_get: | 805 | err_runtime_get: |
| 812 | pm_runtime_disable(&pdev->dev); | 806 | pm_runtime_disable(&pdev->dev); |
| 813 | dss_put_clocks(); | 807 | dss_put_clocks(); |
| 814 | return r; | 808 | return r; |
| 815 | } | 809 | } |
| 816 | 810 | ||
| 817 | static int omap_dsshw_remove(struct platform_device *pdev) | 811 | static int __exit omap_dsshw_remove(struct platform_device *pdev) |
| 818 | { | 812 | { |
| 819 | dpi_exit(); | ||
| 820 | sdi_exit(); | ||
| 821 | |||
| 822 | pm_runtime_disable(&pdev->dev); | 813 | pm_runtime_disable(&pdev->dev); |
| 823 | 814 | ||
| 824 | dss_put_clocks(); | 815 | dss_put_clocks(); |
| @@ -829,11 +820,24 @@ static int omap_dsshw_remove(struct platform_device *pdev) | |||
| 829 | static int dss_runtime_suspend(struct device *dev) | 820 | static int dss_runtime_suspend(struct device *dev) |
| 830 | { | 821 | { |
| 831 | dss_save_context(); | 822 | dss_save_context(); |
| 823 | dss_set_min_bus_tput(dev, 0); | ||
| 832 | return 0; | 824 | return 0; |
| 833 | } | 825 | } |
| 834 | 826 | ||
| 835 | static int dss_runtime_resume(struct device *dev) | 827 | static int dss_runtime_resume(struct device *dev) |
| 836 | { | 828 | { |
| 829 | int r; | ||
| 830 | /* | ||
| 831 | * Set an arbitrarily high tput request to ensure OPP100. | ||
| 832 | * What we should really do is to make a request to stay in OPP100, | ||
| 833 | * without any tput requirements, but that is not currently possible | ||
| 834 | * via the PM layer. | ||
| 835 | */ | ||
| 836 | |||
| 837 | r = dss_set_min_bus_tput(dev, 1000000000); | ||
| 838 | if (r) | ||
| 839 | return r; | ||
| 840 | |||
| 837 | dss_restore_context(); | 841 | dss_restore_context(); |
| 838 | return 0; | 842 | return 0; |
| 839 | } | 843 | } |
| @@ -844,8 +848,7 @@ static const struct dev_pm_ops dss_pm_ops = { | |||
| 844 | }; | 848 | }; |
| 845 | 849 | ||
| 846 | static struct platform_driver omap_dsshw_driver = { | 850 | static struct platform_driver omap_dsshw_driver = { |
| 847 | .probe = omap_dsshw_probe, | 851 | .remove = __exit_p(omap_dsshw_remove), |
| 848 | .remove = omap_dsshw_remove, | ||
| 849 | .driver = { | 852 | .driver = { |
| 850 | .name = "omapdss_dss", | 853 | .name = "omapdss_dss", |
| 851 | .owner = THIS_MODULE, | 854 | .owner = THIS_MODULE, |
| @@ -853,12 +856,12 @@ static struct platform_driver omap_dsshw_driver = { | |||
| 853 | }, | 856 | }, |
| 854 | }; | 857 | }; |
| 855 | 858 | ||
| 856 | int dss_init_platform_driver(void) | 859 | int __init dss_init_platform_driver(void) |
| 857 | { | 860 | { |
| 858 | return platform_driver_register(&omap_dsshw_driver); | 861 | return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe); |
| 859 | } | 862 | } |
| 860 | 863 | ||
| 861 | void dss_uninit_platform_driver(void) | 864 | void dss_uninit_platform_driver(void) |
| 862 | { | 865 | { |
| 863 | return platform_driver_unregister(&omap_dsshw_driver); | 866 | platform_driver_unregister(&omap_dsshw_driver); |
| 864 | } | 867 | } |
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index d4b3dff2ead3..dd1092ceaeef 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
| @@ -150,9 +150,6 @@ struct dsi_clock_info { | |||
| 150 | u16 regm_dsi; /* OMAP3: REGM4 | 150 | u16 regm_dsi; /* OMAP3: REGM4 |
| 151 | * OMAP4: REGM5 */ | 151 | * OMAP4: REGM5 */ |
| 152 | u16 lp_clk_div; | 152 | u16 lp_clk_div; |
| 153 | |||
| 154 | u8 highfreq; | ||
| 155 | bool use_sys_clk; | ||
| 156 | }; | 153 | }; |
| 157 | 154 | ||
| 158 | struct seq_file; | 155 | struct seq_file; |
| @@ -162,6 +159,16 @@ struct platform_device; | |||
| 162 | struct bus_type *dss_get_bus(void); | 159 | struct bus_type *dss_get_bus(void); |
| 163 | struct regulator *dss_get_vdds_dsi(void); | 160 | struct regulator *dss_get_vdds_dsi(void); |
| 164 | struct regulator *dss_get_vdds_sdi(void); | 161 | struct regulator *dss_get_vdds_sdi(void); |
| 162 | int dss_get_ctx_loss_count(struct device *dev); | ||
| 163 | int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask); | ||
| 164 | void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask); | ||
| 165 | int dss_set_min_bus_tput(struct device *dev, unsigned long tput); | ||
| 166 | int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); | ||
| 167 | |||
| 168 | int omap_dss_register_device(struct omap_dss_device *dssdev, | ||
| 169 | struct device *parent, int disp_num); | ||
| 170 | void omap_dss_unregister_device(struct omap_dss_device *dssdev); | ||
| 171 | void omap_dss_unregister_child_devices(struct device *parent); | ||
| 165 | 172 | ||
| 166 | /* apply */ | 173 | /* apply */ |
| 167 | void dss_apply_init(void); | 174 | void dss_apply_init(void); |
| @@ -179,6 +186,9 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr, | |||
| 179 | int dss_mgr_set_device(struct omap_overlay_manager *mgr, | 186 | int dss_mgr_set_device(struct omap_overlay_manager *mgr, |
| 180 | struct omap_dss_device *dssdev); | 187 | struct omap_dss_device *dssdev); |
| 181 | int dss_mgr_unset_device(struct omap_overlay_manager *mgr); | 188 | int dss_mgr_unset_device(struct omap_overlay_manager *mgr); |
| 189 | void dss_mgr_set_timings(struct omap_overlay_manager *mgr, | ||
| 190 | struct omap_video_timings *timings); | ||
| 191 | const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr); | ||
| 182 | 192 | ||
| 183 | bool dss_ovl_is_enabled(struct omap_overlay *ovl); | 193 | bool dss_ovl_is_enabled(struct omap_overlay *ovl); |
| 184 | int dss_ovl_enable(struct omap_overlay *ovl); | 194 | int dss_ovl_enable(struct omap_overlay *ovl); |
| @@ -208,9 +218,11 @@ int dss_init_overlay_managers(struct platform_device *pdev); | |||
| 208 | void dss_uninit_overlay_managers(struct platform_device *pdev); | 218 | void dss_uninit_overlay_managers(struct platform_device *pdev); |
| 209 | int dss_mgr_simple_check(struct omap_overlay_manager *mgr, | 219 | int dss_mgr_simple_check(struct omap_overlay_manager *mgr, |
| 210 | const struct omap_overlay_manager_info *info); | 220 | const struct omap_overlay_manager_info *info); |
| 221 | int dss_mgr_check_timings(struct omap_overlay_manager *mgr, | ||
| 222 | const struct omap_video_timings *timings); | ||
| 211 | int dss_mgr_check(struct omap_overlay_manager *mgr, | 223 | int dss_mgr_check(struct omap_overlay_manager *mgr, |
| 212 | struct omap_dss_device *dssdev, | ||
| 213 | struct omap_overlay_manager_info *info, | 224 | struct omap_overlay_manager_info *info, |
| 225 | const struct omap_video_timings *mgr_timings, | ||
| 214 | struct omap_overlay_info **overlay_infos); | 226 | struct omap_overlay_info **overlay_infos); |
| 215 | 227 | ||
| 216 | /* overlay */ | 228 | /* overlay */ |
| @@ -220,22 +232,18 @@ void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); | |||
| 220 | void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); | 232 | void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); |
| 221 | int dss_ovl_simple_check(struct omap_overlay *ovl, | 233 | int dss_ovl_simple_check(struct omap_overlay *ovl, |
| 222 | const struct omap_overlay_info *info); | 234 | const struct omap_overlay_info *info); |
| 223 | int dss_ovl_check(struct omap_overlay *ovl, | 235 | int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, |
| 224 | struct omap_overlay_info *info, struct omap_dss_device *dssdev); | 236 | const struct omap_video_timings *mgr_timings); |
| 225 | 237 | ||
| 226 | /* DSS */ | 238 | /* DSS */ |
| 227 | int dss_init_platform_driver(void); | 239 | int dss_init_platform_driver(void) __init; |
| 228 | void dss_uninit_platform_driver(void); | 240 | void dss_uninit_platform_driver(void); |
| 229 | 241 | ||
| 230 | int dss_runtime_get(void); | ||
| 231 | void dss_runtime_put(void); | ||
| 232 | |||
| 233 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); | 242 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); |
| 234 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); | 243 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); |
| 235 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); | 244 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); |
| 236 | void dss_dump_clocks(struct seq_file *s); | 245 | void dss_dump_clocks(struct seq_file *s); |
| 237 | 246 | ||
| 238 | void dss_dump_regs(struct seq_file *s); | ||
| 239 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | 247 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) |
| 240 | void dss_debug_dump_clocks(struct seq_file *s); | 248 | void dss_debug_dump_clocks(struct seq_file *s); |
| 241 | #endif | 249 | #endif |
| @@ -265,19 +273,8 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, | |||
| 265 | struct dispc_clock_info *dispc_cinfo); | 273 | struct dispc_clock_info *dispc_cinfo); |
| 266 | 274 | ||
| 267 | /* SDI */ | 275 | /* SDI */ |
| 268 | #ifdef CONFIG_OMAP2_DSS_SDI | 276 | int sdi_init_platform_driver(void) __init; |
| 269 | int sdi_init(void); | 277 | void sdi_uninit_platform_driver(void) __exit; |
| 270 | void sdi_exit(void); | ||
| 271 | int sdi_init_display(struct omap_dss_device *display); | ||
| 272 | #else | ||
| 273 | static inline int sdi_init(void) | ||
| 274 | { | ||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | static inline void sdi_exit(void) | ||
| 278 | { | ||
| 279 | } | ||
| 280 | #endif | ||
| 281 | 278 | ||
| 282 | /* DSI */ | 279 | /* DSI */ |
| 283 | #ifdef CONFIG_OMAP2_DSS_DSI | 280 | #ifdef CONFIG_OMAP2_DSS_DSI |
| @@ -285,19 +282,14 @@ static inline void sdi_exit(void) | |||
| 285 | struct dentry; | 282 | struct dentry; |
| 286 | struct file_operations; | 283 | struct file_operations; |
| 287 | 284 | ||
| 288 | int dsi_init_platform_driver(void); | 285 | int dsi_init_platform_driver(void) __init; |
| 289 | void dsi_uninit_platform_driver(void); | 286 | void dsi_uninit_platform_driver(void) __exit; |
| 290 | 287 | ||
| 291 | int dsi_runtime_get(struct platform_device *dsidev); | 288 | int dsi_runtime_get(struct platform_device *dsidev); |
| 292 | void dsi_runtime_put(struct platform_device *dsidev); | 289 | void dsi_runtime_put(struct platform_device *dsidev); |
| 293 | 290 | ||
| 294 | void dsi_dump_clocks(struct seq_file *s); | 291 | void dsi_dump_clocks(struct seq_file *s); |
| 295 | void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir, | ||
| 296 | const struct file_operations *debug_fops); | ||
| 297 | void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, | ||
| 298 | const struct file_operations *debug_fops); | ||
| 299 | 292 | ||
| 300 | int dsi_init_display(struct omap_dss_device *display); | ||
| 301 | void dsi_irq_handler(void); | 293 | void dsi_irq_handler(void); |
| 302 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); | 294 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); |
| 303 | 295 | ||
| @@ -314,13 +306,6 @@ void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev); | |||
| 314 | void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev); | 306 | void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev); |
| 315 | struct platform_device *dsi_get_dsidev_from_id(int module); | 307 | struct platform_device *dsi_get_dsidev_from_id(int module); |
| 316 | #else | 308 | #else |
| 317 | static inline int dsi_init_platform_driver(void) | ||
| 318 | { | ||
| 319 | return 0; | ||
| 320 | } | ||
| 321 | static inline void dsi_uninit_platform_driver(void) | ||
| 322 | { | ||
| 323 | } | ||
| 324 | static inline int dsi_runtime_get(struct platform_device *dsidev) | 309 | static inline int dsi_runtime_get(struct platform_device *dsidev) |
| 325 | { | 310 | { |
| 326 | return 0; | 311 | return 0; |
| @@ -377,28 +362,14 @@ static inline struct platform_device *dsi_get_dsidev_from_id(int module) | |||
| 377 | #endif | 362 | #endif |
| 378 | 363 | ||
| 379 | /* DPI */ | 364 | /* DPI */ |
| 380 | #ifdef CONFIG_OMAP2_DSS_DPI | 365 | int dpi_init_platform_driver(void) __init; |
| 381 | int dpi_init(void); | 366 | void dpi_uninit_platform_driver(void) __exit; |
| 382 | void dpi_exit(void); | ||
| 383 | int dpi_init_display(struct omap_dss_device *dssdev); | ||
| 384 | #else | ||
| 385 | static inline int dpi_init(void) | ||
| 386 | { | ||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | static inline void dpi_exit(void) | ||
| 390 | { | ||
| 391 | } | ||
| 392 | #endif | ||
| 393 | 367 | ||
| 394 | /* DISPC */ | 368 | /* DISPC */ |
| 395 | int dispc_init_platform_driver(void); | 369 | int dispc_init_platform_driver(void) __init; |
| 396 | void dispc_uninit_platform_driver(void); | 370 | void dispc_uninit_platform_driver(void) __exit; |
| 397 | void dispc_dump_clocks(struct seq_file *s); | 371 | void dispc_dump_clocks(struct seq_file *s); |
| 398 | void dispc_dump_irqs(struct seq_file *s); | ||
| 399 | void dispc_dump_regs(struct seq_file *s); | ||
| 400 | void dispc_irq_handler(void); | 372 | void dispc_irq_handler(void); |
| 401 | void dispc_fake_vsync_irq(void); | ||
| 402 | 373 | ||
| 403 | int dispc_runtime_get(void); | 374 | int dispc_runtime_get(void); |
| 404 | void dispc_runtime_put(void); | 375 | void dispc_runtime_put(void); |
| @@ -409,12 +380,12 @@ void dispc_disable_sidle(void); | |||
| 409 | void dispc_lcd_enable_signal_polarity(bool act_high); | 380 | void dispc_lcd_enable_signal_polarity(bool act_high); |
| 410 | void dispc_lcd_enable_signal(bool enable); | 381 | void dispc_lcd_enable_signal(bool enable); |
| 411 | void dispc_pck_free_enable(bool enable); | 382 | void dispc_pck_free_enable(bool enable); |
| 412 | void dispc_set_digit_size(u16 width, u16 height); | ||
| 413 | void dispc_enable_fifomerge(bool enable); | 383 | void dispc_enable_fifomerge(bool enable); |
| 414 | void dispc_enable_gamma_table(bool enable); | 384 | void dispc_enable_gamma_table(bool enable); |
| 415 | void dispc_set_loadmode(enum omap_dss_load_mode mode); | 385 | void dispc_set_loadmode(enum omap_dss_load_mode mode); |
| 416 | 386 | ||
| 417 | bool dispc_lcd_timings_ok(struct omap_video_timings *timings); | 387 | bool dispc_mgr_timings_ok(enum omap_channel channel, |
| 388 | const struct omap_video_timings *timings); | ||
| 418 | unsigned long dispc_fclk_rate(void); | 389 | unsigned long dispc_fclk_rate(void); |
| 419 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, | 390 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, |
| 420 | struct dispc_clock_info *cinfo); | 391 | struct dispc_clock_info *cinfo); |
| @@ -424,15 +395,16 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | |||
| 424 | 395 | ||
| 425 | void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); | 396 | void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); |
| 426 | void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, | 397 | void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, |
| 427 | u32 *fifo_low, u32 *fifo_high, bool use_fifomerge); | 398 | u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, |
| 399 | bool manual_update); | ||
| 428 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | 400 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, |
| 429 | bool ilace, bool replication); | 401 | bool ilace, bool replication, |
| 402 | const struct omap_video_timings *mgr_timings); | ||
| 430 | int dispc_ovl_enable(enum omap_plane plane, bool enable); | 403 | int dispc_ovl_enable(enum omap_plane plane, bool enable); |
| 431 | void dispc_ovl_set_channel_out(enum omap_plane plane, | 404 | void dispc_ovl_set_channel_out(enum omap_plane plane, |
| 432 | enum omap_channel channel); | 405 | enum omap_channel channel); |
| 433 | 406 | ||
| 434 | void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); | 407 | void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); |
| 435 | void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height); | ||
| 436 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); | 408 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); |
| 437 | u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); | 409 | u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); |
| 438 | bool dispc_mgr_go_busy(enum omap_channel channel); | 410 | bool dispc_mgr_go_busy(enum omap_channel channel); |
| @@ -445,12 +417,13 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable); | |||
| 445 | void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); | 417 | void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); |
| 446 | void dispc_mgr_set_lcd_display_type(enum omap_channel channel, | 418 | void dispc_mgr_set_lcd_display_type(enum omap_channel channel, |
| 447 | enum omap_lcd_display_type type); | 419 | enum omap_lcd_display_type type); |
| 448 | void dispc_mgr_set_lcd_timings(enum omap_channel channel, | 420 | void dispc_mgr_set_timings(enum omap_channel channel, |
| 449 | struct omap_video_timings *timings); | 421 | struct omap_video_timings *timings); |
| 450 | void dispc_mgr_set_pol_freq(enum omap_channel channel, | 422 | void dispc_mgr_set_pol_freq(enum omap_channel channel, |
| 451 | enum omap_panel_config config, u8 acbi, u8 acb); | 423 | enum omap_panel_config config, u8 acbi, u8 acb); |
| 452 | unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); | 424 | unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); |
| 453 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); | 425 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); |
| 426 | unsigned long dispc_core_clk_rate(void); | ||
| 454 | int dispc_mgr_set_clock_div(enum omap_channel channel, | 427 | int dispc_mgr_set_clock_div(enum omap_channel channel, |
| 455 | struct dispc_clock_info *cinfo); | 428 | struct dispc_clock_info *cinfo); |
| 456 | int dispc_mgr_get_clock_div(enum omap_channel channel, | 429 | int dispc_mgr_get_clock_div(enum omap_channel channel, |
| @@ -460,19 +433,10 @@ void dispc_mgr_setup(enum omap_channel channel, | |||
| 460 | 433 | ||
| 461 | /* VENC */ | 434 | /* VENC */ |
| 462 | #ifdef CONFIG_OMAP2_DSS_VENC | 435 | #ifdef CONFIG_OMAP2_DSS_VENC |
| 463 | int venc_init_platform_driver(void); | 436 | int venc_init_platform_driver(void) __init; |
| 464 | void venc_uninit_platform_driver(void); | 437 | void venc_uninit_platform_driver(void) __exit; |
| 465 | void venc_dump_regs(struct seq_file *s); | ||
| 466 | int venc_init_display(struct omap_dss_device *display); | ||
| 467 | unsigned long venc_get_pixel_clock(void); | 438 | unsigned long venc_get_pixel_clock(void); |
| 468 | #else | 439 | #else |
| 469 | static inline int venc_init_platform_driver(void) | ||
| 470 | { | ||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | static inline void venc_uninit_platform_driver(void) | ||
| 474 | { | ||
| 475 | } | ||
| 476 | static inline unsigned long venc_get_pixel_clock(void) | 440 | static inline unsigned long venc_get_pixel_clock(void) |
| 477 | { | 441 | { |
| 478 | WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__); | 442 | WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__); |
| @@ -482,23 +446,10 @@ static inline unsigned long venc_get_pixel_clock(void) | |||
| 482 | 446 | ||
| 483 | /* HDMI */ | 447 | /* HDMI */ |
| 484 | #ifdef CONFIG_OMAP4_DSS_HDMI | 448 | #ifdef CONFIG_OMAP4_DSS_HDMI |
| 485 | int hdmi_init_platform_driver(void); | 449 | int hdmi_init_platform_driver(void) __init; |
| 486 | void hdmi_uninit_platform_driver(void); | 450 | void hdmi_uninit_platform_driver(void) __exit; |
| 487 | int hdmi_init_display(struct omap_dss_device *dssdev); | ||
| 488 | unsigned long hdmi_get_pixel_clock(void); | 451 | unsigned long hdmi_get_pixel_clock(void); |
| 489 | void hdmi_dump_regs(struct seq_file *s); | ||
| 490 | #else | 452 | #else |
| 491 | static inline int hdmi_init_display(struct omap_dss_device *dssdev) | ||
| 492 | { | ||
| 493 | return 0; | ||
| 494 | } | ||
| 495 | static inline int hdmi_init_platform_driver(void) | ||
| 496 | { | ||
| 497 | return 0; | ||
| 498 | } | ||
| 499 | static inline void hdmi_uninit_platform_driver(void) | ||
| 500 | { | ||
| 501 | } | ||
| 502 | static inline unsigned long hdmi_get_pixel_clock(void) | 453 | static inline unsigned long hdmi_get_pixel_clock(void) |
| 503 | { | 454 | { |
| 504 | WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__); | 455 | WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__); |
| @@ -514,22 +465,18 @@ int omapdss_hdmi_read_edid(u8 *buf, int len); | |||
| 514 | bool omapdss_hdmi_detect(void); | 465 | bool omapdss_hdmi_detect(void); |
| 515 | int hdmi_panel_init(void); | 466 | int hdmi_panel_init(void); |
| 516 | void hdmi_panel_exit(void); | 467 | void hdmi_panel_exit(void); |
| 468 | #ifdef CONFIG_OMAP4_DSS_HDMI_AUDIO | ||
| 469 | int hdmi_audio_enable(void); | ||
| 470 | void hdmi_audio_disable(void); | ||
| 471 | int hdmi_audio_start(void); | ||
| 472 | void hdmi_audio_stop(void); | ||
| 473 | bool hdmi_mode_has_audio(void); | ||
| 474 | int hdmi_audio_config(struct omap_dss_audio *audio); | ||
| 475 | #endif | ||
| 517 | 476 | ||
| 518 | /* RFBI */ | 477 | /* RFBI */ |
| 519 | #ifdef CONFIG_OMAP2_DSS_RFBI | 478 | int rfbi_init_platform_driver(void) __init; |
| 520 | int rfbi_init_platform_driver(void); | 479 | void rfbi_uninit_platform_driver(void) __exit; |
| 521 | void rfbi_uninit_platform_driver(void); | ||
| 522 | void rfbi_dump_regs(struct seq_file *s); | ||
| 523 | int rfbi_init_display(struct omap_dss_device *display); | ||
| 524 | #else | ||
| 525 | static inline int rfbi_init_platform_driver(void) | ||
| 526 | { | ||
| 527 | return 0; | ||
| 528 | } | ||
| 529 | static inline void rfbi_uninit_platform_driver(void) | ||
| 530 | { | ||
| 531 | } | ||
| 532 | #endif | ||
| 533 | 480 | ||
| 534 | 481 | ||
| 535 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 482 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index ce14aa6dd672..938709724f0c 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
| @@ -52,6 +52,8 @@ struct omap_dss_features { | |||
| 52 | const char * const *clksrc_names; | 52 | const char * const *clksrc_names; |
| 53 | const struct dss_param_range *dss_params; | 53 | const struct dss_param_range *dss_params; |
| 54 | 54 | ||
| 55 | const enum omap_dss_rotation_type supported_rotation_types; | ||
| 56 | |||
| 55 | const u32 buffer_size_unit; | 57 | const u32 buffer_size_unit; |
| 56 | const u32 burst_size_unit; | 58 | const u32 burst_size_unit; |
| 57 | }; | 59 | }; |
| @@ -311,6 +313,8 @@ static const struct dss_param_range omap2_dss_param_range[] = { | |||
| 311 | * scaler cannot scale a image with width more than 768. | 313 | * scaler cannot scale a image with width more than 768. |
| 312 | */ | 314 | */ |
| 313 | [FEAT_PARAM_LINEWIDTH] = { 1, 768 }, | 315 | [FEAT_PARAM_LINEWIDTH] = { 1, 768 }, |
| 316 | [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, | ||
| 317 | [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, | ||
| 314 | }; | 318 | }; |
| 315 | 319 | ||
| 316 | static const struct dss_param_range omap3_dss_param_range[] = { | 320 | static const struct dss_param_range omap3_dss_param_range[] = { |
| @@ -324,6 +328,8 @@ static const struct dss_param_range omap3_dss_param_range[] = { | |||
| 324 | [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, | 328 | [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, |
| 325 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, | 329 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, |
| 326 | [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, | 330 | [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, |
| 331 | [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, | ||
| 332 | [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, | ||
| 327 | }; | 333 | }; |
| 328 | 334 | ||
| 329 | static const struct dss_param_range omap4_dss_param_range[] = { | 335 | static const struct dss_param_range omap4_dss_param_range[] = { |
| @@ -337,6 +343,8 @@ static const struct dss_param_range omap4_dss_param_range[] = { | |||
| 337 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, | 343 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, |
| 338 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, | 344 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, |
| 339 | [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, | 345 | [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, |
| 346 | [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, | ||
| 347 | [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, | ||
| 340 | }; | 348 | }; |
| 341 | 349 | ||
| 342 | static const enum dss_feat_id omap2_dss_feat_list[] = { | 350 | static const enum dss_feat_id omap2_dss_feat_list[] = { |
| @@ -399,6 +407,7 @@ static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = { | |||
| 399 | FEAT_FIR_COEF_V, | 407 | FEAT_FIR_COEF_V, |
| 400 | FEAT_ALPHA_FREE_ZORDER, | 408 | FEAT_ALPHA_FREE_ZORDER, |
| 401 | FEAT_FIFO_MERGE, | 409 | FEAT_FIFO_MERGE, |
| 410 | FEAT_BURST_2D, | ||
| 402 | }; | 411 | }; |
| 403 | 412 | ||
| 404 | static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = { | 413 | static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = { |
| @@ -416,6 +425,7 @@ static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = { | |||
| 416 | FEAT_FIR_COEF_V, | 425 | FEAT_FIR_COEF_V, |
| 417 | FEAT_ALPHA_FREE_ZORDER, | 426 | FEAT_ALPHA_FREE_ZORDER, |
| 418 | FEAT_FIFO_MERGE, | 427 | FEAT_FIFO_MERGE, |
| 428 | FEAT_BURST_2D, | ||
| 419 | }; | 429 | }; |
| 420 | 430 | ||
| 421 | static const enum dss_feat_id omap4_dss_feat_list[] = { | 431 | static const enum dss_feat_id omap4_dss_feat_list[] = { |
| @@ -434,6 +444,7 @@ static const enum dss_feat_id omap4_dss_feat_list[] = { | |||
| 434 | FEAT_FIR_COEF_V, | 444 | FEAT_FIR_COEF_V, |
| 435 | FEAT_ALPHA_FREE_ZORDER, | 445 | FEAT_ALPHA_FREE_ZORDER, |
| 436 | FEAT_FIFO_MERGE, | 446 | FEAT_FIFO_MERGE, |
| 447 | FEAT_BURST_2D, | ||
| 437 | }; | 448 | }; |
| 438 | 449 | ||
| 439 | /* OMAP2 DSS Features */ | 450 | /* OMAP2 DSS Features */ |
| @@ -451,6 +462,7 @@ static const struct omap_dss_features omap2_dss_features = { | |||
| 451 | .overlay_caps = omap2_dss_overlay_caps, | 462 | .overlay_caps = omap2_dss_overlay_caps, |
| 452 | .clksrc_names = omap2_dss_clk_source_names, | 463 | .clksrc_names = omap2_dss_clk_source_names, |
| 453 | .dss_params = omap2_dss_param_range, | 464 | .dss_params = omap2_dss_param_range, |
| 465 | .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, | ||
| 454 | .buffer_size_unit = 1, | 466 | .buffer_size_unit = 1, |
| 455 | .burst_size_unit = 8, | 467 | .burst_size_unit = 8, |
| 456 | }; | 468 | }; |
| @@ -470,6 +482,7 @@ static const struct omap_dss_features omap3430_dss_features = { | |||
| 470 | .overlay_caps = omap3430_dss_overlay_caps, | 482 | .overlay_caps = omap3430_dss_overlay_caps, |
| 471 | .clksrc_names = omap3_dss_clk_source_names, | 483 | .clksrc_names = omap3_dss_clk_source_names, |
| 472 | .dss_params = omap3_dss_param_range, | 484 | .dss_params = omap3_dss_param_range, |
| 485 | .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, | ||
| 473 | .buffer_size_unit = 1, | 486 | .buffer_size_unit = 1, |
| 474 | .burst_size_unit = 8, | 487 | .burst_size_unit = 8, |
| 475 | }; | 488 | }; |
| @@ -488,6 +501,7 @@ static const struct omap_dss_features omap3630_dss_features = { | |||
| 488 | .overlay_caps = omap3630_dss_overlay_caps, | 501 | .overlay_caps = omap3630_dss_overlay_caps, |
| 489 | .clksrc_names = omap3_dss_clk_source_names, | 502 | .clksrc_names = omap3_dss_clk_source_names, |
| 490 | .dss_params = omap3_dss_param_range, | 503 | .dss_params = omap3_dss_param_range, |
| 504 | .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, | ||
| 491 | .buffer_size_unit = 1, | 505 | .buffer_size_unit = 1, |
| 492 | .burst_size_unit = 8, | 506 | .burst_size_unit = 8, |
| 493 | }; | 507 | }; |
| @@ -508,6 +522,7 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { | |||
| 508 | .overlay_caps = omap4_dss_overlay_caps, | 522 | .overlay_caps = omap4_dss_overlay_caps, |
| 509 | .clksrc_names = omap4_dss_clk_source_names, | 523 | .clksrc_names = omap4_dss_clk_source_names, |
| 510 | .dss_params = omap4_dss_param_range, | 524 | .dss_params = omap4_dss_param_range, |
| 525 | .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, | ||
| 511 | .buffer_size_unit = 16, | 526 | .buffer_size_unit = 16, |
| 512 | .burst_size_unit = 16, | 527 | .burst_size_unit = 16, |
| 513 | }; | 528 | }; |
| @@ -527,6 +542,7 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = { | |||
| 527 | .overlay_caps = omap4_dss_overlay_caps, | 542 | .overlay_caps = omap4_dss_overlay_caps, |
| 528 | .clksrc_names = omap4_dss_clk_source_names, | 543 | .clksrc_names = omap4_dss_clk_source_names, |
| 529 | .dss_params = omap4_dss_param_range, | 544 | .dss_params = omap4_dss_param_range, |
| 545 | .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, | ||
| 530 | .buffer_size_unit = 16, | 546 | .buffer_size_unit = 16, |
| 531 | .burst_size_unit = 16, | 547 | .burst_size_unit = 16, |
| 532 | }; | 548 | }; |
| @@ -546,6 +562,7 @@ static const struct omap_dss_features omap4_dss_features = { | |||
| 546 | .overlay_caps = omap4_dss_overlay_caps, | 562 | .overlay_caps = omap4_dss_overlay_caps, |
| 547 | .clksrc_names = omap4_dss_clk_source_names, | 563 | .clksrc_names = omap4_dss_clk_source_names, |
| 548 | .dss_params = omap4_dss_param_range, | 564 | .dss_params = omap4_dss_param_range, |
| 565 | .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, | ||
| 549 | .buffer_size_unit = 16, | 566 | .buffer_size_unit = 16, |
| 550 | .burst_size_unit = 16, | 567 | .burst_size_unit = 16, |
| 551 | }; | 568 | }; |
| @@ -562,13 +579,17 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { | |||
| 562 | .pll_enable = ti_hdmi_4xxx_pll_enable, | 579 | .pll_enable = ti_hdmi_4xxx_pll_enable, |
| 563 | .pll_disable = ti_hdmi_4xxx_pll_disable, | 580 | .pll_disable = ti_hdmi_4xxx_pll_disable, |
| 564 | .video_enable = ti_hdmi_4xxx_wp_video_start, | 581 | .video_enable = ti_hdmi_4xxx_wp_video_start, |
| 582 | .video_disable = ti_hdmi_4xxx_wp_video_stop, | ||
| 565 | .dump_wrapper = ti_hdmi_4xxx_wp_dump, | 583 | .dump_wrapper = ti_hdmi_4xxx_wp_dump, |
| 566 | .dump_core = ti_hdmi_4xxx_core_dump, | 584 | .dump_core = ti_hdmi_4xxx_core_dump, |
| 567 | .dump_pll = ti_hdmi_4xxx_pll_dump, | 585 | .dump_pll = ti_hdmi_4xxx_pll_dump, |
| 568 | .dump_phy = ti_hdmi_4xxx_phy_dump, | 586 | .dump_phy = ti_hdmi_4xxx_phy_dump, |
| 569 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 587 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) |
| 570 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
| 571 | .audio_enable = ti_hdmi_4xxx_wp_audio_enable, | 588 | .audio_enable = ti_hdmi_4xxx_wp_audio_enable, |
| 589 | .audio_disable = ti_hdmi_4xxx_wp_audio_disable, | ||
| 590 | .audio_start = ti_hdmi_4xxx_audio_start, | ||
| 591 | .audio_stop = ti_hdmi_4xxx_audio_stop, | ||
| 592 | .audio_config = ti_hdmi_4xxx_audio_config, | ||
| 572 | #endif | 593 | #endif |
| 573 | 594 | ||
| 574 | }; | 595 | }; |
| @@ -662,6 +683,11 @@ void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end) | |||
| 662 | *end = omap_current_dss_features->reg_fields[id].end; | 683 | *end = omap_current_dss_features->reg_fields[id].end; |
| 663 | } | 684 | } |
| 664 | 685 | ||
| 686 | bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type) | ||
| 687 | { | ||
| 688 | return omap_current_dss_features->supported_rotation_types & rot_type; | ||
| 689 | } | ||
| 690 | |||
| 665 | void dss_features_init(void) | 691 | void dss_features_init(void) |
| 666 | { | 692 | { |
| 667 | if (cpu_is_omap24xx()) | 693 | if (cpu_is_omap24xx()) |
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index c332e7ddfce1..bdf469f080e7 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h | |||
| @@ -62,6 +62,7 @@ enum dss_feat_id { | |||
| 62 | FEAT_FIFO_MERGE, | 62 | FEAT_FIFO_MERGE, |
| 63 | /* An unknown HW bug causing the normal FIFO thresholds not to work */ | 63 | /* An unknown HW bug causing the normal FIFO thresholds not to work */ |
| 64 | FEAT_OMAP3_DSI_FIFO_BUG, | 64 | FEAT_OMAP3_DSI_FIFO_BUG, |
| 65 | FEAT_BURST_2D, | ||
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 67 | /* DSS register field id */ | 68 | /* DSS register field id */ |
| @@ -91,6 +92,8 @@ enum dss_range_param { | |||
| 91 | FEAT_PARAM_DSIPLL_LPDIV, | 92 | FEAT_PARAM_DSIPLL_LPDIV, |
| 92 | FEAT_PARAM_DOWNSCALE, | 93 | FEAT_PARAM_DOWNSCALE, |
| 93 | FEAT_PARAM_LINEWIDTH, | 94 | FEAT_PARAM_LINEWIDTH, |
| 95 | FEAT_PARAM_MGR_WIDTH, | ||
| 96 | FEAT_PARAM_MGR_HEIGHT, | ||
| 94 | }; | 97 | }; |
| 95 | 98 | ||
| 96 | /* DSS Feature Functions */ | 99 | /* DSS Feature Functions */ |
| @@ -108,6 +111,8 @@ const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id); | |||
| 108 | u32 dss_feat_get_buffer_size_unit(void); /* in bytes */ | 111 | u32 dss_feat_get_buffer_size_unit(void); /* in bytes */ |
| 109 | u32 dss_feat_get_burst_size_unit(void); /* in bytes */ | 112 | u32 dss_feat_get_burst_size_unit(void); /* in bytes */ |
| 110 | 113 | ||
| 114 | bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type); | ||
| 115 | |||
| 111 | bool dss_has_feature(enum dss_feat_id id); | 116 | bool dss_has_feature(enum dss_feat_id id); |
| 112 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); | 117 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); |
| 113 | void dss_features_init(void); | 118 | void dss_features_init(void); |
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index c4b4f6950a92..8195c7166d20 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c | |||
| @@ -33,12 +33,6 @@ | |||
| 33 | #include <linux/pm_runtime.h> | 33 | #include <linux/pm_runtime.h> |
| 34 | #include <linux/clk.h> | 34 | #include <linux/clk.h> |
| 35 | #include <video/omapdss.h> | 35 | #include <video/omapdss.h> |
| 36 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
| 37 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
| 38 | #include <sound/soc.h> | ||
| 39 | #include <sound/pcm_params.h> | ||
| 40 | #include "ti_hdmi_4xxx_ip.h" | ||
| 41 | #endif | ||
| 42 | 36 | ||
| 43 | #include "ti_hdmi.h" | 37 | #include "ti_hdmi.h" |
| 44 | #include "dss.h" | 38 | #include "dss.h" |
| @@ -63,7 +57,6 @@ | |||
| 63 | 57 | ||
| 64 | static struct { | 58 | static struct { |
| 65 | struct mutex lock; | 59 | struct mutex lock; |
| 66 | struct omap_display_platform_data *pdata; | ||
| 67 | struct platform_device *pdev; | 60 | struct platform_device *pdev; |
| 68 | struct hdmi_ip_data ip_data; | 61 | struct hdmi_ip_data ip_data; |
| 69 | 62 | ||
| @@ -130,25 +123,12 @@ static int hdmi_runtime_get(void) | |||
| 130 | 123 | ||
| 131 | DSSDBG("hdmi_runtime_get\n"); | 124 | DSSDBG("hdmi_runtime_get\n"); |
| 132 | 125 | ||
| 133 | /* | ||
| 134 | * HACK: Add dss_runtime_get() to ensure DSS clock domain is enabled. | ||
| 135 | * This should be removed later. | ||
| 136 | */ | ||
| 137 | r = dss_runtime_get(); | ||
| 138 | if (r < 0) | ||
| 139 | goto err_get_dss; | ||
| 140 | |||
| 141 | r = pm_runtime_get_sync(&hdmi.pdev->dev); | 126 | r = pm_runtime_get_sync(&hdmi.pdev->dev); |
| 142 | WARN_ON(r < 0); | 127 | WARN_ON(r < 0); |
| 143 | if (r < 0) | 128 | if (r < 0) |
| 144 | goto err_get_hdmi; | 129 | return r; |
| 145 | 130 | ||
| 146 | return 0; | 131 | return 0; |
| 147 | |||
| 148 | err_get_hdmi: | ||
| 149 | dss_runtime_put(); | ||
| 150 | err_get_dss: | ||
| 151 | return r; | ||
| 152 | } | 132 | } |
| 153 | 133 | ||
| 154 | static void hdmi_runtime_put(void) | 134 | static void hdmi_runtime_put(void) |
| @@ -159,15 +139,9 @@ static void hdmi_runtime_put(void) | |||
| 159 | 139 | ||
| 160 | r = pm_runtime_put_sync(&hdmi.pdev->dev); | 140 | r = pm_runtime_put_sync(&hdmi.pdev->dev); |
| 161 | WARN_ON(r < 0); | 141 | WARN_ON(r < 0); |
| 162 | |||
| 163 | /* | ||
| 164 | * HACK: This is added to complement the dss_runtime_get() call in | ||
| 165 | * hdmi_runtime_get(). This should be removed later. | ||
| 166 | */ | ||
| 167 | dss_runtime_put(); | ||
| 168 | } | 142 | } |
| 169 | 143 | ||
| 170 | int hdmi_init_display(struct omap_dss_device *dssdev) | 144 | static int __init hdmi_init_display(struct omap_dss_device *dssdev) |
| 171 | { | 145 | { |
| 172 | DSSDBG("init_display\n"); | 146 | DSSDBG("init_display\n"); |
| 173 | 147 | ||
| @@ -344,7 +318,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
| 344 | 318 | ||
| 345 | hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); | 319 | hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); |
| 346 | 320 | ||
| 347 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); | 321 | hdmi.ip_data.ops->video_disable(&hdmi.ip_data); |
| 348 | 322 | ||
| 349 | /* config the PLL and PHY hdmi_set_pll_pwrfirst */ | 323 | /* config the PLL and PHY hdmi_set_pll_pwrfirst */ |
| 350 | r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); | 324 | r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); |
| @@ -376,10 +350,11 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
| 376 | dispc_enable_gamma_table(0); | 350 | dispc_enable_gamma_table(0); |
| 377 | 351 | ||
| 378 | /* tv size */ | 352 | /* tv size */ |
| 379 | dispc_set_digit_size(dssdev->panel.timings.x_res, | 353 | dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); |
| 380 | dssdev->panel.timings.y_res); | ||
| 381 | 354 | ||
| 382 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1); | 355 | r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data); |
| 356 | if (r) | ||
| 357 | goto err_vid_enable; | ||
| 383 | 358 | ||
| 384 | r = dss_mgr_enable(dssdev->manager); | 359 | r = dss_mgr_enable(dssdev->manager); |
| 385 | if (r) | 360 | if (r) |
| @@ -388,7 +363,8 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
| 388 | return 0; | 363 | return 0; |
| 389 | 364 | ||
| 390 | err_mgr_enable: | 365 | err_mgr_enable: |
| 391 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); | 366 | hdmi.ip_data.ops->video_disable(&hdmi.ip_data); |
| 367 | err_vid_enable: | ||
| 392 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); | 368 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); |
| 393 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); | 369 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); |
| 394 | err: | 370 | err: |
| @@ -400,7 +376,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev) | |||
| 400 | { | 376 | { |
| 401 | dss_mgr_disable(dssdev->manager); | 377 | dss_mgr_disable(dssdev->manager); |
| 402 | 378 | ||
| 403 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); | 379 | hdmi.ip_data.ops->video_disable(&hdmi.ip_data); |
| 404 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); | 380 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); |
| 405 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); | 381 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); |
| 406 | hdmi_runtime_put(); | 382 | hdmi_runtime_put(); |
| @@ -436,10 +412,12 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) | |||
| 436 | r = hdmi_power_on(dssdev); | 412 | r = hdmi_power_on(dssdev); |
| 437 | if (r) | 413 | if (r) |
| 438 | DSSERR("failed to power on device\n"); | 414 | DSSERR("failed to power on device\n"); |
| 415 | } else { | ||
| 416 | dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); | ||
| 439 | } | 417 | } |
| 440 | } | 418 | } |
| 441 | 419 | ||
| 442 | void hdmi_dump_regs(struct seq_file *s) | 420 | static void hdmi_dump_regs(struct seq_file *s) |
| 443 | { | 421 | { |
| 444 | mutex_lock(&hdmi.lock); | 422 | mutex_lock(&hdmi.lock); |
| 445 | 423 | ||
| @@ -555,248 +533,201 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) | |||
| 555 | mutex_unlock(&hdmi.lock); | 533 | mutex_unlock(&hdmi.lock); |
| 556 | } | 534 | } |
| 557 | 535 | ||
| 558 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 536 | static int hdmi_get_clocks(struct platform_device *pdev) |
| 559 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
| 560 | |||
| 561 | static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, | ||
| 562 | struct snd_soc_dai *dai) | ||
| 563 | { | 537 | { |
| 564 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 538 | struct clk *clk; |
| 565 | struct snd_soc_codec *codec = rtd->codec; | ||
| 566 | struct platform_device *pdev = to_platform_device(codec->dev); | ||
| 567 | struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec); | ||
| 568 | int err = 0; | ||
| 569 | 539 | ||
| 570 | if (!(ip_data->ops) && !(ip_data->ops->audio_enable)) { | 540 | clk = clk_get(&pdev->dev, "sys_clk"); |
| 571 | dev_err(&pdev->dev, "Cannot enable/disable audio\n"); | 541 | if (IS_ERR(clk)) { |
| 572 | return -ENODEV; | 542 | DSSERR("can't get sys_clk\n"); |
| 543 | return PTR_ERR(clk); | ||
| 573 | } | 544 | } |
| 574 | 545 | ||
| 575 | switch (cmd) { | 546 | hdmi.sys_clk = clk; |
| 576 | case SNDRV_PCM_TRIGGER_START: | 547 | |
| 577 | case SNDRV_PCM_TRIGGER_RESUME: | 548 | return 0; |
| 578 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 549 | } |
| 579 | ip_data->ops->audio_enable(ip_data, true); | 550 | |
| 580 | break; | 551 | static void hdmi_put_clocks(void) |
| 581 | case SNDRV_PCM_TRIGGER_STOP: | 552 | { |
| 582 | case SNDRV_PCM_TRIGGER_SUSPEND: | 553 | if (hdmi.sys_clk) |
| 583 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 554 | clk_put(hdmi.sys_clk); |
| 584 | ip_data->ops->audio_enable(ip_data, false); | 555 | } |
| 585 | break; | 556 | |
| 586 | default: | 557 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) |
| 587 | err = -EINVAL; | 558 | int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts) |
| 588 | } | 559 | { |
| 589 | return err; | 560 | u32 deep_color; |
| 590 | } | 561 | bool deep_color_correct = false; |
| 591 | 562 | u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock; | |
| 592 | static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | 563 | |
| 593 | struct snd_pcm_hw_params *params, | 564 | if (n == NULL || cts == NULL) |
| 594 | struct snd_soc_dai *dai) | ||
| 595 | { | ||
| 596 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 597 | struct snd_soc_codec *codec = rtd->codec; | ||
| 598 | struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec); | ||
| 599 | struct hdmi_audio_format audio_format; | ||
| 600 | struct hdmi_audio_dma audio_dma; | ||
| 601 | struct hdmi_core_audio_config core_cfg; | ||
| 602 | struct hdmi_core_infoframe_audio aud_if_cfg; | ||
| 603 | int err, n, cts; | ||
| 604 | enum hdmi_core_audio_sample_freq sample_freq; | ||
| 605 | |||
| 606 | switch (params_format(params)) { | ||
| 607 | case SNDRV_PCM_FORMAT_S16_LE: | ||
| 608 | core_cfg.i2s_cfg.word_max_length = | ||
| 609 | HDMI_AUDIO_I2S_MAX_WORD_20BITS; | ||
| 610 | core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_16_BITS; | ||
| 611 | core_cfg.i2s_cfg.in_length_bits = | ||
| 612 | HDMI_AUDIO_I2S_INPUT_LENGTH_16; | ||
| 613 | core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT; | ||
| 614 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES; | ||
| 615 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS; | ||
| 616 | audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT; | ||
| 617 | audio_dma.transfer_size = 0x10; | ||
| 618 | break; | ||
| 619 | case SNDRV_PCM_FORMAT_S24_LE: | ||
| 620 | core_cfg.i2s_cfg.word_max_length = | ||
| 621 | HDMI_AUDIO_I2S_MAX_WORD_24BITS; | ||
| 622 | core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_24_BITS; | ||
| 623 | core_cfg.i2s_cfg.in_length_bits = | ||
| 624 | HDMI_AUDIO_I2S_INPUT_LENGTH_24; | ||
| 625 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE; | ||
| 626 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS; | ||
| 627 | audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT; | ||
| 628 | core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT; | ||
| 629 | audio_dma.transfer_size = 0x20; | ||
| 630 | break; | ||
| 631 | default: | ||
| 632 | return -EINVAL; | 565 | return -EINVAL; |
| 633 | } | ||
| 634 | 566 | ||
| 635 | switch (params_rate(params)) { | 567 | /* TODO: When implemented, query deep color mode here. */ |
| 568 | deep_color = 100; | ||
| 569 | |||
| 570 | /* | ||
| 571 | * When using deep color, the default N value (as in the HDMI | ||
| 572 | * specification) yields to an non-integer CTS. Hence, we | ||
| 573 | * modify it while keeping the restrictions described in | ||
| 574 | * section 7.2.1 of the HDMI 1.4a specification. | ||
| 575 | */ | ||
| 576 | switch (sample_freq) { | ||
| 636 | case 32000: | 577 | case 32000: |
| 637 | sample_freq = HDMI_AUDIO_FS_32000; | 578 | case 48000: |
| 579 | case 96000: | ||
| 580 | case 192000: | ||
| 581 | if (deep_color == 125) | ||
| 582 | if (pclk == 27027 || pclk == 74250) | ||
| 583 | deep_color_correct = true; | ||
| 584 | if (deep_color == 150) | ||
| 585 | if (pclk == 27027) | ||
| 586 | deep_color_correct = true; | ||
| 638 | break; | 587 | break; |
| 639 | case 44100: | 588 | case 44100: |
| 640 | sample_freq = HDMI_AUDIO_FS_44100; | 589 | case 88200: |
| 641 | break; | 590 | case 176400: |
| 642 | case 48000: | 591 | if (deep_color == 125) |
| 643 | sample_freq = HDMI_AUDIO_FS_48000; | 592 | if (pclk == 27027) |
| 593 | deep_color_correct = true; | ||
| 644 | break; | 594 | break; |
| 645 | default: | 595 | default: |
| 646 | return -EINVAL; | 596 | return -EINVAL; |
| 647 | } | 597 | } |
| 648 | 598 | ||
| 649 | err = hdmi_config_audio_acr(ip_data, params_rate(params), &n, &cts); | 599 | if (deep_color_correct) { |
| 650 | if (err < 0) | 600 | switch (sample_freq) { |
| 651 | return err; | 601 | case 32000: |
| 652 | 602 | *n = 8192; | |
| 653 | /* Audio wrapper config */ | 603 | break; |
| 654 | audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; | 604 | case 44100: |
| 655 | audio_format.active_chnnls_msk = 0x03; | 605 | *n = 12544; |
| 656 | audio_format.type = HDMI_AUDIO_TYPE_LPCM; | 606 | break; |
| 657 | audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST; | 607 | case 48000: |
| 658 | /* Disable start/stop signals of IEC 60958 blocks */ | 608 | *n = 8192; |
| 659 | audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF; | 609 | break; |
| 610 | case 88200: | ||
| 611 | *n = 25088; | ||
| 612 | break; | ||
| 613 | case 96000: | ||
| 614 | *n = 16384; | ||
| 615 | break; | ||
| 616 | case 176400: | ||
| 617 | *n = 50176; | ||
| 618 | break; | ||
| 619 | case 192000: | ||
| 620 | *n = 32768; | ||
| 621 | break; | ||
| 622 | default: | ||
| 623 | return -EINVAL; | ||
| 624 | } | ||
| 625 | } else { | ||
| 626 | switch (sample_freq) { | ||
| 627 | case 32000: | ||
| 628 | *n = 4096; | ||
| 629 | break; | ||
| 630 | case 44100: | ||
| 631 | *n = 6272; | ||
| 632 | break; | ||
| 633 | case 48000: | ||
| 634 | *n = 6144; | ||
| 635 | break; | ||
| 636 | case 88200: | ||
| 637 | *n = 12544; | ||
| 638 | break; | ||
| 639 | case 96000: | ||
| 640 | *n = 12288; | ||
| 641 | break; | ||
| 642 | case 176400: | ||
| 643 | *n = 25088; | ||
| 644 | break; | ||
| 645 | case 192000: | ||
| 646 | *n = 24576; | ||
| 647 | break; | ||
| 648 | default: | ||
| 649 | return -EINVAL; | ||
| 650 | } | ||
| 651 | } | ||
| 652 | /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ | ||
| 653 | *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); | ||
| 660 | 654 | ||
| 661 | audio_dma.block_size = 0xC0; | 655 | return 0; |
| 662 | audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; | 656 | } |
| 663 | audio_dma.fifo_threshold = 0x20; /* in number of samples */ | ||
| 664 | 657 | ||
| 665 | hdmi_wp_audio_config_dma(ip_data, &audio_dma); | 658 | int hdmi_audio_enable(void) |
| 666 | hdmi_wp_audio_config_format(ip_data, &audio_format); | 659 | { |
| 660 | DSSDBG("audio_enable\n"); | ||
| 667 | 661 | ||
| 668 | /* | 662 | return hdmi.ip_data.ops->audio_enable(&hdmi.ip_data); |
| 669 | * I2S config | 663 | } |
| 670 | */ | ||
| 671 | core_cfg.i2s_cfg.en_high_bitrate_aud = false; | ||
| 672 | /* Only used with high bitrate audio */ | ||
| 673 | core_cfg.i2s_cfg.cbit_order = false; | ||
| 674 | /* Serial data and word select should change on sck rising edge */ | ||
| 675 | core_cfg.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING; | ||
| 676 | core_cfg.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM; | ||
| 677 | /* Set I2S word select polarity */ | ||
| 678 | core_cfg.i2s_cfg.ws_polarity = HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT; | ||
| 679 | core_cfg.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST; | ||
| 680 | /* Set serial data to word select shift. See Phillips spec. */ | ||
| 681 | core_cfg.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT; | ||
| 682 | /* Enable one of the four available serial data channels */ | ||
| 683 | core_cfg.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN; | ||
| 684 | |||
| 685 | /* Core audio config */ | ||
| 686 | core_cfg.freq_sample = sample_freq; | ||
| 687 | core_cfg.n = n; | ||
| 688 | core_cfg.cts = cts; | ||
| 689 | if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { | ||
| 690 | core_cfg.aud_par_busclk = 0; | ||
| 691 | core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW; | ||
| 692 | core_cfg.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK); | ||
| 693 | } else { | ||
| 694 | core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8); | ||
| 695 | core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW; | ||
| 696 | core_cfg.use_mclk = true; | ||
| 697 | } | ||
| 698 | 664 | ||
| 699 | if (core_cfg.use_mclk) | 665 | void hdmi_audio_disable(void) |
| 700 | core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS; | 666 | { |
| 701 | core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH; | 667 | DSSDBG("audio_disable\n"); |
| 702 | core_cfg.en_spdif = false; | ||
| 703 | /* Use sample frequency from channel status word */ | ||
| 704 | core_cfg.fs_override = true; | ||
| 705 | /* Enable ACR packets */ | ||
| 706 | core_cfg.en_acr_pkt = true; | ||
| 707 | /* Disable direct streaming digital audio */ | ||
| 708 | core_cfg.en_dsd_audio = false; | ||
| 709 | /* Use parallel audio interface */ | ||
| 710 | core_cfg.en_parallel_aud_input = true; | ||
| 711 | |||
| 712 | hdmi_core_audio_config(ip_data, &core_cfg); | ||
| 713 | 668 | ||
| 714 | /* | 669 | hdmi.ip_data.ops->audio_disable(&hdmi.ip_data); |
| 715 | * Configure packet | ||
| 716 | * info frame audio see doc CEA861-D page 74 | ||
| 717 | */ | ||
| 718 | aud_if_cfg.db1_coding_type = HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM; | ||
| 719 | aud_if_cfg.db1_channel_count = 2; | ||
| 720 | aud_if_cfg.db2_sample_freq = HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM; | ||
| 721 | aud_if_cfg.db2_sample_size = HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM; | ||
| 722 | aud_if_cfg.db4_channel_alloc = 0x00; | ||
| 723 | aud_if_cfg.db5_downmix_inh = false; | ||
| 724 | aud_if_cfg.db5_lsv = 0; | ||
| 725 | |||
| 726 | hdmi_core_audio_infoframe_config(ip_data, &aud_if_cfg); | ||
| 727 | return 0; | ||
| 728 | } | 670 | } |
| 729 | 671 | ||
| 730 | static int hdmi_audio_startup(struct snd_pcm_substream *substream, | 672 | int hdmi_audio_start(void) |
| 731 | struct snd_soc_dai *dai) | ||
| 732 | { | 673 | { |
| 733 | if (!hdmi.ip_data.cfg.cm.mode) { | 674 | DSSDBG("audio_start\n"); |
| 734 | pr_err("Current video settings do not support audio.\n"); | 675 | |
| 735 | return -EIO; | 676 | return hdmi.ip_data.ops->audio_start(&hdmi.ip_data); |
| 736 | } | ||
| 737 | return 0; | ||
| 738 | } | 677 | } |
| 739 | 678 | ||
| 740 | static int hdmi_audio_codec_probe(struct snd_soc_codec *codec) | 679 | void hdmi_audio_stop(void) |
| 741 | { | 680 | { |
| 742 | struct hdmi_ip_data *priv = &hdmi.ip_data; | 681 | DSSDBG("audio_stop\n"); |
| 743 | 682 | ||
| 744 | snd_soc_codec_set_drvdata(codec, priv); | 683 | hdmi.ip_data.ops->audio_stop(&hdmi.ip_data); |
| 745 | return 0; | ||
| 746 | } | 684 | } |
| 747 | 685 | ||
| 748 | static struct snd_soc_codec_driver hdmi_audio_codec_drv = { | 686 | bool hdmi_mode_has_audio(void) |
| 749 | .probe = hdmi_audio_codec_probe, | 687 | { |
| 750 | }; | 688 | if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI) |
| 689 | return true; | ||
| 690 | else | ||
| 691 | return false; | ||
| 692 | } | ||
| 751 | 693 | ||
| 752 | static struct snd_soc_dai_ops hdmi_audio_codec_ops = { | 694 | int hdmi_audio_config(struct omap_dss_audio *audio) |
| 753 | .hw_params = hdmi_audio_hw_params, | 695 | { |
| 754 | .trigger = hdmi_audio_trigger, | 696 | return hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio); |
| 755 | .startup = hdmi_audio_startup, | 697 | } |
| 756 | }; | ||
| 757 | 698 | ||
| 758 | static struct snd_soc_dai_driver hdmi_codec_dai_drv = { | ||
| 759 | .name = "hdmi-audio-codec", | ||
| 760 | .playback = { | ||
| 761 | .channels_min = 2, | ||
| 762 | .channels_max = 2, | ||
| 763 | .rates = SNDRV_PCM_RATE_32000 | | ||
| 764 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, | ||
| 765 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
| 766 | SNDRV_PCM_FMTBIT_S24_LE, | ||
| 767 | }, | ||
| 768 | .ops = &hdmi_audio_codec_ops, | ||
| 769 | }; | ||
| 770 | #endif | 699 | #endif |
| 771 | 700 | ||
| 772 | static int hdmi_get_clocks(struct platform_device *pdev) | 701 | static void __init hdmi_probe_pdata(struct platform_device *pdev) |
| 773 | { | 702 | { |
| 774 | struct clk *clk; | 703 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
| 704 | int r, i; | ||
| 775 | 705 | ||
| 776 | clk = clk_get(&pdev->dev, "sys_clk"); | 706 | for (i = 0; i < pdata->num_devices; ++i) { |
| 777 | if (IS_ERR(clk)) { | 707 | struct omap_dss_device *dssdev = pdata->devices[i]; |
| 778 | DSSERR("can't get sys_clk\n"); | ||
| 779 | return PTR_ERR(clk); | ||
| 780 | } | ||
| 781 | 708 | ||
| 782 | hdmi.sys_clk = clk; | 709 | if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI) |
| 710 | continue; | ||
| 783 | 711 | ||
| 784 | return 0; | 712 | r = hdmi_init_display(dssdev); |
| 785 | } | 713 | if (r) { |
| 714 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | ||
| 715 | continue; | ||
| 716 | } | ||
| 786 | 717 | ||
| 787 | static void hdmi_put_clocks(void) | 718 | r = omap_dss_register_device(dssdev, &pdev->dev, i); |
| 788 | { | 719 | if (r) |
| 789 | if (hdmi.sys_clk) | 720 | DSSERR("device %s register failed: %d\n", |
| 790 | clk_put(hdmi.sys_clk); | 721 | dssdev->name, r); |
| 722 | } | ||
| 791 | } | 723 | } |
| 792 | 724 | ||
| 793 | /* HDMI HW IP initialisation */ | 725 | /* HDMI HW IP initialisation */ |
| 794 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | 726 | static int __init omapdss_hdmihw_probe(struct platform_device *pdev) |
| 795 | { | 727 | { |
| 796 | struct resource *hdmi_mem; | 728 | struct resource *hdmi_mem; |
| 797 | int r; | 729 | int r; |
| 798 | 730 | ||
| 799 | hdmi.pdata = pdev->dev.platform_data; | ||
| 800 | hdmi.pdev = pdev; | 731 | hdmi.pdev = pdev; |
| 801 | 732 | ||
| 802 | mutex_init(&hdmi.lock); | 733 | mutex_init(&hdmi.lock); |
| @@ -830,28 +761,18 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev) | |||
| 830 | 761 | ||
| 831 | hdmi_panel_init(); | 762 | hdmi_panel_init(); |
| 832 | 763 | ||
| 833 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 764 | dss_debugfs_create_file("hdmi", hdmi_dump_regs); |
| 834 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | 765 | |
| 766 | hdmi_probe_pdata(pdev); | ||
| 835 | 767 | ||
| 836 | /* Register ASoC codec DAI */ | ||
| 837 | r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv, | ||
| 838 | &hdmi_codec_dai_drv, 1); | ||
| 839 | if (r) { | ||
| 840 | DSSERR("can't register ASoC HDMI audio codec\n"); | ||
| 841 | return r; | ||
| 842 | } | ||
| 843 | #endif | ||
| 844 | return 0; | 768 | return 0; |
| 845 | } | 769 | } |
| 846 | 770 | ||
| 847 | static int omapdss_hdmihw_remove(struct platform_device *pdev) | 771 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) |
| 848 | { | 772 | { |
| 849 | hdmi_panel_exit(); | 773 | omap_dss_unregister_child_devices(&pdev->dev); |
| 850 | 774 | ||
| 851 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 775 | hdmi_panel_exit(); |
| 852 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
| 853 | snd_soc_unregister_codec(&pdev->dev); | ||
| 854 | #endif | ||
| 855 | 776 | ||
| 856 | pm_runtime_disable(&pdev->dev); | 777 | pm_runtime_disable(&pdev->dev); |
| 857 | 778 | ||
| @@ -867,7 +788,6 @@ static int hdmi_runtime_suspend(struct device *dev) | |||
| 867 | clk_disable(hdmi.sys_clk); | 788 | clk_disable(hdmi.sys_clk); |
| 868 | 789 | ||
| 869 | dispc_runtime_put(); | 790 | dispc_runtime_put(); |
| 870 | dss_runtime_put(); | ||
| 871 | 791 | ||
| 872 | return 0; | 792 | return 0; |
| 873 | } | 793 | } |
| @@ -876,23 +796,13 @@ static int hdmi_runtime_resume(struct device *dev) | |||
| 876 | { | 796 | { |
| 877 | int r; | 797 | int r; |
| 878 | 798 | ||
| 879 | r = dss_runtime_get(); | ||
| 880 | if (r < 0) | ||
| 881 | goto err_get_dss; | ||
| 882 | |||
| 883 | r = dispc_runtime_get(); | 799 | r = dispc_runtime_get(); |
| 884 | if (r < 0) | 800 | if (r < 0) |
| 885 | goto err_get_dispc; | 801 | return r; |
| 886 | |||
| 887 | 802 | ||
| 888 | clk_enable(hdmi.sys_clk); | 803 | clk_enable(hdmi.sys_clk); |
| 889 | 804 | ||
| 890 | return 0; | 805 | return 0; |
| 891 | |||
| 892 | err_get_dispc: | ||
| 893 | dss_runtime_put(); | ||
| 894 | err_get_dss: | ||
| 895 | return r; | ||
| 896 | } | 806 | } |
| 897 | 807 | ||
| 898 | static const struct dev_pm_ops hdmi_pm_ops = { | 808 | static const struct dev_pm_ops hdmi_pm_ops = { |
| @@ -901,8 +811,7 @@ static const struct dev_pm_ops hdmi_pm_ops = { | |||
| 901 | }; | 811 | }; |
| 902 | 812 | ||
| 903 | static struct platform_driver omapdss_hdmihw_driver = { | 813 | static struct platform_driver omapdss_hdmihw_driver = { |
| 904 | .probe = omapdss_hdmihw_probe, | 814 | .remove = __exit_p(omapdss_hdmihw_remove), |
| 905 | .remove = omapdss_hdmihw_remove, | ||
| 906 | .driver = { | 815 | .driver = { |
| 907 | .name = "omapdss_hdmi", | 816 | .name = "omapdss_hdmi", |
| 908 | .owner = THIS_MODULE, | 817 | .owner = THIS_MODULE, |
| @@ -910,12 +819,12 @@ static struct platform_driver omapdss_hdmihw_driver = { | |||
| 910 | }, | 819 | }, |
| 911 | }; | 820 | }; |
| 912 | 821 | ||
| 913 | int hdmi_init_platform_driver(void) | 822 | int __init hdmi_init_platform_driver(void) |
| 914 | { | 823 | { |
| 915 | return platform_driver_register(&omapdss_hdmihw_driver); | 824 | return platform_driver_probe(&omapdss_hdmihw_driver, omapdss_hdmihw_probe); |
| 916 | } | 825 | } |
| 917 | 826 | ||
| 918 | void hdmi_uninit_platform_driver(void) | 827 | void __exit hdmi_uninit_platform_driver(void) |
| 919 | { | 828 | { |
| 920 | return platform_driver_unregister(&omapdss_hdmihw_driver); | 829 | platform_driver_unregister(&omapdss_hdmihw_driver); |
| 921 | } | 830 | } |
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c index 533d5dc634d2..1179e3c4b1c7 100644 --- a/drivers/video/omap2/dss/hdmi_panel.c +++ b/drivers/video/omap2/dss/hdmi_panel.c | |||
| @@ -30,7 +30,12 @@ | |||
| 30 | #include "dss.h" | 30 | #include "dss.h" |
| 31 | 31 | ||
| 32 | static struct { | 32 | static struct { |
| 33 | struct mutex hdmi_lock; | 33 | /* This protects the panel ops, mainly when accessing the HDMI IP. */ |
| 34 | struct mutex lock; | ||
| 35 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) | ||
| 36 | /* This protects the audio ops, specifically. */ | ||
| 37 | spinlock_t audio_lock; | ||
| 38 | #endif | ||
| 34 | } hdmi; | 39 | } hdmi; |
| 35 | 40 | ||
| 36 | 41 | ||
| @@ -54,12 +59,168 @@ static void hdmi_panel_remove(struct omap_dss_device *dssdev) | |||
| 54 | 59 | ||
| 55 | } | 60 | } |
| 56 | 61 | ||
| 62 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) | ||
| 63 | static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev) | ||
| 64 | { | ||
| 65 | unsigned long flags; | ||
| 66 | int r; | ||
| 67 | |||
| 68 | mutex_lock(&hdmi.lock); | ||
| 69 | spin_lock_irqsave(&hdmi.audio_lock, flags); | ||
| 70 | |||
| 71 | /* enable audio only if the display is active and supports audio */ | ||
| 72 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || | ||
| 73 | !hdmi_mode_has_audio()) { | ||
| 74 | DSSERR("audio not supported or display is off\n"); | ||
| 75 | r = -EPERM; | ||
| 76 | goto err; | ||
| 77 | } | ||
| 78 | |||
| 79 | r = hdmi_audio_enable(); | ||
| 80 | |||
| 81 | if (!r) | ||
| 82 | dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED; | ||
| 83 | |||
| 84 | err: | ||
| 85 | spin_unlock_irqrestore(&hdmi.audio_lock, flags); | ||
| 86 | mutex_unlock(&hdmi.lock); | ||
| 87 | return r; | ||
| 88 | } | ||
| 89 | |||
| 90 | static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev) | ||
| 91 | { | ||
| 92 | unsigned long flags; | ||
| 93 | |||
| 94 | spin_lock_irqsave(&hdmi.audio_lock, flags); | ||
| 95 | |||
| 96 | hdmi_audio_disable(); | ||
| 97 | |||
| 98 | dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED; | ||
| 99 | |||
| 100 | spin_unlock_irqrestore(&hdmi.audio_lock, flags); | ||
| 101 | } | ||
| 102 | |||
| 103 | static int hdmi_panel_audio_start(struct omap_dss_device *dssdev) | ||
| 104 | { | ||
| 105 | unsigned long flags; | ||
| 106 | int r; | ||
| 107 | |||
| 108 | spin_lock_irqsave(&hdmi.audio_lock, flags); | ||
| 109 | /* | ||
| 110 | * No need to check the panel state. It was checked when trasitioning | ||
| 111 | * to AUDIO_ENABLED. | ||
| 112 | */ | ||
| 113 | if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED) { | ||
| 114 | DSSERR("audio start from invalid state\n"); | ||
| 115 | r = -EPERM; | ||
| 116 | goto err; | ||
| 117 | } | ||
| 118 | |||
| 119 | r = hdmi_audio_start(); | ||
| 120 | |||
| 121 | if (!r) | ||
| 122 | dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING; | ||
| 123 | |||
| 124 | err: | ||
| 125 | spin_unlock_irqrestore(&hdmi.audio_lock, flags); | ||
| 126 | return r; | ||
| 127 | } | ||
| 128 | |||
| 129 | static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev) | ||
| 130 | { | ||
| 131 | unsigned long flags; | ||
| 132 | |||
| 133 | spin_lock_irqsave(&hdmi.audio_lock, flags); | ||
| 134 | |||
| 135 | hdmi_audio_stop(); | ||
| 136 | dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED; | ||
| 137 | |||
| 138 | spin_unlock_irqrestore(&hdmi.audio_lock, flags); | ||
| 139 | } | ||
| 140 | |||
| 141 | static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev) | ||
| 142 | { | ||
| 143 | bool r = false; | ||
| 144 | |||
| 145 | mutex_lock(&hdmi.lock); | ||
| 146 | |||
| 147 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
| 148 | goto err; | ||
| 149 | |||
| 150 | if (!hdmi_mode_has_audio()) | ||
| 151 | goto err; | ||
| 152 | |||
| 153 | r = true; | ||
| 154 | err: | ||
| 155 | mutex_unlock(&hdmi.lock); | ||
| 156 | return r; | ||
| 157 | } | ||
| 158 | |||
| 159 | static int hdmi_panel_audio_config(struct omap_dss_device *dssdev, | ||
| 160 | struct omap_dss_audio *audio) | ||
| 161 | { | ||
| 162 | unsigned long flags; | ||
| 163 | int r; | ||
| 164 | |||
| 165 | mutex_lock(&hdmi.lock); | ||
| 166 | spin_lock_irqsave(&hdmi.audio_lock, flags); | ||
| 167 | |||
| 168 | /* config audio only if the display is active and supports audio */ | ||
| 169 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || | ||
| 170 | !hdmi_mode_has_audio()) { | ||
| 171 | DSSERR("audio not supported or display is off\n"); | ||
| 172 | r = -EPERM; | ||
| 173 | goto err; | ||
| 174 | } | ||
| 175 | |||
| 176 | r = hdmi_audio_config(audio); | ||
| 177 | |||
| 178 | if (!r) | ||
| 179 | dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED; | ||
| 180 | |||
| 181 | err: | ||
| 182 | spin_unlock_irqrestore(&hdmi.audio_lock, flags); | ||
| 183 | mutex_unlock(&hdmi.lock); | ||
| 184 | return r; | ||
| 185 | } | ||
| 186 | |||
| 187 | #else | ||
| 188 | static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev) | ||
| 189 | { | ||
| 190 | return -EPERM; | ||
| 191 | } | ||
| 192 | |||
| 193 | static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev) | ||
| 194 | { | ||
| 195 | } | ||
| 196 | |||
| 197 | static int hdmi_panel_audio_start(struct omap_dss_device *dssdev) | ||
| 198 | { | ||
| 199 | return -EPERM; | ||
| 200 | } | ||
| 201 | |||
| 202 | static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev) | ||
| 203 | { | ||
| 204 | } | ||
| 205 | |||
| 206 | static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev) | ||
| 207 | { | ||
| 208 | return false; | ||
| 209 | } | ||
| 210 | |||
| 211 | static int hdmi_panel_audio_config(struct omap_dss_device *dssdev, | ||
| 212 | struct omap_dss_audio *audio) | ||
| 213 | { | ||
| 214 | return -EPERM; | ||
| 215 | } | ||
| 216 | #endif | ||
| 217 | |||
| 57 | static int hdmi_panel_enable(struct omap_dss_device *dssdev) | 218 | static int hdmi_panel_enable(struct omap_dss_device *dssdev) |
| 58 | { | 219 | { |
| 59 | int r = 0; | 220 | int r = 0; |
| 60 | DSSDBG("ENTER hdmi_panel_enable\n"); | 221 | DSSDBG("ENTER hdmi_panel_enable\n"); |
| 61 | 222 | ||
| 62 | mutex_lock(&hdmi.hdmi_lock); | 223 | mutex_lock(&hdmi.lock); |
| 63 | 224 | ||
| 64 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { | 225 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { |
| 65 | r = -EINVAL; | 226 | r = -EINVAL; |
| @@ -75,40 +236,52 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev) | |||
| 75 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 236 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
| 76 | 237 | ||
| 77 | err: | 238 | err: |
| 78 | mutex_unlock(&hdmi.hdmi_lock); | 239 | mutex_unlock(&hdmi.lock); |
| 79 | 240 | ||
| 80 | return r; | 241 | return r; |
| 81 | } | 242 | } |
| 82 | 243 | ||
| 83 | static void hdmi_panel_disable(struct omap_dss_device *dssdev) | 244 | static void hdmi_panel_disable(struct omap_dss_device *dssdev) |
| 84 | { | 245 | { |
| 85 | mutex_lock(&hdmi.hdmi_lock); | 246 | mutex_lock(&hdmi.lock); |
| 86 | 247 | ||
| 87 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | 248 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { |
| 249 | /* | ||
| 250 | * TODO: notify audio users that the display was disabled. For | ||
| 251 | * now, disable audio locally to not break our audio state | ||
| 252 | * machine. | ||
| 253 | */ | ||
| 254 | hdmi_panel_audio_disable(dssdev); | ||
| 88 | omapdss_hdmi_display_disable(dssdev); | 255 | omapdss_hdmi_display_disable(dssdev); |
| 256 | } | ||
| 89 | 257 | ||
| 90 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 258 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; |
| 91 | 259 | ||
| 92 | mutex_unlock(&hdmi.hdmi_lock); | 260 | mutex_unlock(&hdmi.lock); |
| 93 | } | 261 | } |
| 94 | 262 | ||
| 95 | static int hdmi_panel_suspend(struct omap_dss_device *dssdev) | 263 | static int hdmi_panel_suspend(struct omap_dss_device *dssdev) |
| 96 | { | 264 | { |
| 97 | int r = 0; | 265 | int r = 0; |
| 98 | 266 | ||
| 99 | mutex_lock(&hdmi.hdmi_lock); | 267 | mutex_lock(&hdmi.lock); |
| 100 | 268 | ||
| 101 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | 269 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { |
| 102 | r = -EINVAL; | 270 | r = -EINVAL; |
| 103 | goto err; | 271 | goto err; |
| 104 | } | 272 | } |
| 105 | 273 | ||
| 106 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | 274 | /* |
| 275 | * TODO: notify audio users that the display was suspended. For now, | ||
| 276 | * disable audio locally to not break our audio state machine. | ||
| 277 | */ | ||
| 278 | hdmi_panel_audio_disable(dssdev); | ||
| 107 | 279 | ||
| 280 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
| 108 | omapdss_hdmi_display_disable(dssdev); | 281 | omapdss_hdmi_display_disable(dssdev); |
| 109 | 282 | ||
| 110 | err: | 283 | err: |
| 111 | mutex_unlock(&hdmi.hdmi_lock); | 284 | mutex_unlock(&hdmi.lock); |
| 112 | 285 | ||
| 113 | return r; | 286 | return r; |
| 114 | } | 287 | } |
| @@ -117,7 +290,7 @@ static int hdmi_panel_resume(struct omap_dss_device *dssdev) | |||
| 117 | { | 290 | { |
| 118 | int r = 0; | 291 | int r = 0; |
| 119 | 292 | ||
| 120 | mutex_lock(&hdmi.hdmi_lock); | 293 | mutex_lock(&hdmi.lock); |
| 121 | 294 | ||
| 122 | if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { | 295 | if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { |
| 123 | r = -EINVAL; | 296 | r = -EINVAL; |
| @@ -129,11 +302,12 @@ static int hdmi_panel_resume(struct omap_dss_device *dssdev) | |||
| 129 | DSSERR("failed to power on\n"); | 302 | DSSERR("failed to power on\n"); |
| 130 | goto err; | 303 | goto err; |
| 131 | } | 304 | } |
| 305 | /* TODO: notify audio users that the panel resumed. */ | ||
| 132 | 306 | ||
| 133 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 307 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
| 134 | 308 | ||
| 135 | err: | 309 | err: |
| 136 | mutex_unlock(&hdmi.hdmi_lock); | 310 | mutex_unlock(&hdmi.lock); |
| 137 | 311 | ||
| 138 | return r; | 312 | return r; |
| 139 | } | 313 | } |
| @@ -141,11 +315,11 @@ err: | |||
| 141 | static void hdmi_get_timings(struct omap_dss_device *dssdev, | 315 | static void hdmi_get_timings(struct omap_dss_device *dssdev, |
| 142 | struct omap_video_timings *timings) | 316 | struct omap_video_timings *timings) |
| 143 | { | 317 | { |
| 144 | mutex_lock(&hdmi.hdmi_lock); | 318 | mutex_lock(&hdmi.lock); |
| 145 | 319 | ||
| 146 | *timings = dssdev->panel.timings; | 320 | *timings = dssdev->panel.timings; |
| 147 | 321 | ||
| 148 | mutex_unlock(&hdmi.hdmi_lock); | 322 | mutex_unlock(&hdmi.lock); |
| 149 | } | 323 | } |
| 150 | 324 | ||
| 151 | static void hdmi_set_timings(struct omap_dss_device *dssdev, | 325 | static void hdmi_set_timings(struct omap_dss_device *dssdev, |
| @@ -153,12 +327,18 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev, | |||
| 153 | { | 327 | { |
| 154 | DSSDBG("hdmi_set_timings\n"); | 328 | DSSDBG("hdmi_set_timings\n"); |
| 155 | 329 | ||
| 156 | mutex_lock(&hdmi.hdmi_lock); | 330 | mutex_lock(&hdmi.lock); |
| 331 | |||
| 332 | /* | ||
| 333 | * TODO: notify audio users that there was a timings change. For | ||
| 334 | * now, disable audio locally to not break our audio state machine. | ||
| 335 | */ | ||
| 336 | hdmi_panel_audio_disable(dssdev); | ||
| 157 | 337 | ||
| 158 | dssdev->panel.timings = *timings; | 338 | dssdev->panel.timings = *timings; |
| 159 | omapdss_hdmi_display_set_timing(dssdev); | 339 | omapdss_hdmi_display_set_timing(dssdev); |
| 160 | 340 | ||
| 161 | mutex_unlock(&hdmi.hdmi_lock); | 341 | mutex_unlock(&hdmi.lock); |
| 162 | } | 342 | } |
| 163 | 343 | ||
| 164 | static int hdmi_check_timings(struct omap_dss_device *dssdev, | 344 | static int hdmi_check_timings(struct omap_dss_device *dssdev, |
| @@ -168,11 +348,11 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev, | |||
| 168 | 348 | ||
| 169 | DSSDBG("hdmi_check_timings\n"); | 349 | DSSDBG("hdmi_check_timings\n"); |
| 170 | 350 | ||
| 171 | mutex_lock(&hdmi.hdmi_lock); | 351 | mutex_lock(&hdmi.lock); |
| 172 | 352 | ||
| 173 | r = omapdss_hdmi_display_check_timing(dssdev, timings); | 353 | r = omapdss_hdmi_display_check_timing(dssdev, timings); |
| 174 | 354 | ||
| 175 | mutex_unlock(&hdmi.hdmi_lock); | 355 | mutex_unlock(&hdmi.lock); |
| 176 | return r; | 356 | return r; |
| 177 | } | 357 | } |
| 178 | 358 | ||
| @@ -180,7 +360,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len) | |||
| 180 | { | 360 | { |
| 181 | int r; | 361 | int r; |
| 182 | 362 | ||
| 183 | mutex_lock(&hdmi.hdmi_lock); | 363 | mutex_lock(&hdmi.lock); |
| 184 | 364 | ||
| 185 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | 365 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { |
| 186 | r = omapdss_hdmi_display_enable(dssdev); | 366 | r = omapdss_hdmi_display_enable(dssdev); |
| @@ -194,7 +374,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len) | |||
| 194 | dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) | 374 | dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) |
| 195 | omapdss_hdmi_display_disable(dssdev); | 375 | omapdss_hdmi_display_disable(dssdev); |
| 196 | err: | 376 | err: |
| 197 | mutex_unlock(&hdmi.hdmi_lock); | 377 | mutex_unlock(&hdmi.lock); |
| 198 | 378 | ||
| 199 | return r; | 379 | return r; |
| 200 | } | 380 | } |
| @@ -203,7 +383,7 @@ static bool hdmi_detect(struct omap_dss_device *dssdev) | |||
| 203 | { | 383 | { |
| 204 | int r; | 384 | int r; |
| 205 | 385 | ||
| 206 | mutex_lock(&hdmi.hdmi_lock); | 386 | mutex_lock(&hdmi.lock); |
| 207 | 387 | ||
| 208 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | 388 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { |
| 209 | r = omapdss_hdmi_display_enable(dssdev); | 389 | r = omapdss_hdmi_display_enable(dssdev); |
| @@ -217,7 +397,7 @@ static bool hdmi_detect(struct omap_dss_device *dssdev) | |||
| 217 | dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) | 397 | dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) |
| 218 | omapdss_hdmi_display_disable(dssdev); | 398 | omapdss_hdmi_display_disable(dssdev); |
| 219 | err: | 399 | err: |
| 220 | mutex_unlock(&hdmi.hdmi_lock); | 400 | mutex_unlock(&hdmi.lock); |
| 221 | 401 | ||
| 222 | return r; | 402 | return r; |
| 223 | } | 403 | } |
| @@ -234,6 +414,12 @@ static struct omap_dss_driver hdmi_driver = { | |||
| 234 | .check_timings = hdmi_check_timings, | 414 | .check_timings = hdmi_check_timings, |
| 235 | .read_edid = hdmi_read_edid, | 415 | .read_edid = hdmi_read_edid, |
| 236 | .detect = hdmi_detect, | 416 | .detect = hdmi_detect, |
| 417 | .audio_enable = hdmi_panel_audio_enable, | ||
| 418 | .audio_disable = hdmi_panel_audio_disable, | ||
| 419 | .audio_start = hdmi_panel_audio_start, | ||
| 420 | .audio_stop = hdmi_panel_audio_stop, | ||
| 421 | .audio_supported = hdmi_panel_audio_supported, | ||
| 422 | .audio_config = hdmi_panel_audio_config, | ||
| 237 | .driver = { | 423 | .driver = { |
| 238 | .name = "hdmi_panel", | 424 | .name = "hdmi_panel", |
| 239 | .owner = THIS_MODULE, | 425 | .owner = THIS_MODULE, |
| @@ -242,7 +428,11 @@ static struct omap_dss_driver hdmi_driver = { | |||
| 242 | 428 | ||
| 243 | int hdmi_panel_init(void) | 429 | int hdmi_panel_init(void) |
| 244 | { | 430 | { |
| 245 | mutex_init(&hdmi.hdmi_lock); | 431 | mutex_init(&hdmi.lock); |
| 432 | |||
| 433 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) | ||
| 434 | spin_lock_init(&hdmi.audio_lock); | ||
| 435 | #endif | ||
| 246 | 436 | ||
| 247 | omap_dss_register_driver(&hdmi_driver); | 437 | omap_dss_register_driver(&hdmi_driver); |
| 248 | 438 | ||
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index e7364603f6a1..0cbcde4c688a 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c | |||
| @@ -654,9 +654,20 @@ static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr, | |||
| 654 | return 0; | 654 | return 0; |
| 655 | } | 655 | } |
| 656 | 656 | ||
| 657 | int dss_mgr_check_timings(struct omap_overlay_manager *mgr, | ||
| 658 | const struct omap_video_timings *timings) | ||
| 659 | { | ||
| 660 | if (!dispc_mgr_timings_ok(mgr->id, timings)) { | ||
| 661 | DSSERR("check_manager: invalid timings\n"); | ||
| 662 | return -EINVAL; | ||
| 663 | } | ||
| 664 | |||
| 665 | return 0; | ||
| 666 | } | ||
| 667 | |||
| 657 | int dss_mgr_check(struct omap_overlay_manager *mgr, | 668 | int dss_mgr_check(struct omap_overlay_manager *mgr, |
| 658 | struct omap_dss_device *dssdev, | ||
| 659 | struct omap_overlay_manager_info *info, | 669 | struct omap_overlay_manager_info *info, |
| 670 | const struct omap_video_timings *mgr_timings, | ||
| 660 | struct omap_overlay_info **overlay_infos) | 671 | struct omap_overlay_info **overlay_infos) |
| 661 | { | 672 | { |
| 662 | struct omap_overlay *ovl; | 673 | struct omap_overlay *ovl; |
| @@ -668,6 +679,10 @@ int dss_mgr_check(struct omap_overlay_manager *mgr, | |||
| 668 | return r; | 679 | return r; |
| 669 | } | 680 | } |
| 670 | 681 | ||
| 682 | r = dss_mgr_check_timings(mgr, mgr_timings); | ||
| 683 | if (r) | ||
| 684 | return r; | ||
| 685 | |||
| 671 | list_for_each_entry(ovl, &mgr->overlays, list) { | 686 | list_for_each_entry(ovl, &mgr->overlays, list) { |
| 672 | struct omap_overlay_info *oi; | 687 | struct omap_overlay_info *oi; |
| 673 | int r; | 688 | int r; |
| @@ -677,7 +692,7 @@ int dss_mgr_check(struct omap_overlay_manager *mgr, | |||
| 677 | if (oi == NULL) | 692 | if (oi == NULL) |
| 678 | continue; | 693 | continue; |
| 679 | 694 | ||
| 680 | r = dss_ovl_check(ovl, oi, dssdev); | 695 | r = dss_ovl_check(ovl, oi, mgr_timings); |
| 681 | if (r) | 696 | if (r) |
| 682 | return r; | 697 | return r; |
| 683 | } | 698 | } |
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 6e821810deec..b0ba60f88dd2 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c | |||
| @@ -628,19 +628,23 @@ int dss_ovl_simple_check(struct omap_overlay *ovl, | |||
| 628 | return -EINVAL; | 628 | return -EINVAL; |
| 629 | } | 629 | } |
| 630 | 630 | ||
| 631 | if (dss_feat_rotation_type_supported(info->rotation_type) == 0) { | ||
| 632 | DSSERR("check_overlay: rotation type %d not supported\n", | ||
| 633 | info->rotation_type); | ||
| 634 | return -EINVAL; | ||
| 635 | } | ||
| 636 | |||
| 631 | return 0; | 637 | return 0; |
| 632 | } | 638 | } |
| 633 | 639 | ||
| 634 | int dss_ovl_check(struct omap_overlay *ovl, | 640 | int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, |
| 635 | struct omap_overlay_info *info, struct omap_dss_device *dssdev) | 641 | const struct omap_video_timings *mgr_timings) |
| 636 | { | 642 | { |
| 637 | u16 outw, outh; | 643 | u16 outw, outh; |
| 638 | u16 dw, dh; | 644 | u16 dw, dh; |
| 639 | 645 | ||
| 640 | if (dssdev == NULL) | 646 | dw = mgr_timings->x_res; |
| 641 | return 0; | 647 | dh = mgr_timings->y_res; |
| 642 | |||
| 643 | dssdev->driver->get_resolution(dssdev, &dw, &dh); | ||
| 644 | 648 | ||
| 645 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { | 649 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { |
| 646 | outw = info->width; | 650 | outw = info->width; |
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 788a0ef6323a..3d8c206e90e5 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c | |||
| @@ -304,13 +304,23 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, | |||
| 304 | u16 height, void (*callback)(void *data), void *data) | 304 | u16 height, void (*callback)(void *data), void *data) |
| 305 | { | 305 | { |
| 306 | u32 l; | 306 | u32 l; |
| 307 | struct omap_video_timings timings = { | ||
| 308 | .hsw = 1, | ||
| 309 | .hfp = 1, | ||
| 310 | .hbp = 1, | ||
| 311 | .vsw = 1, | ||
| 312 | .vfp = 0, | ||
| 313 | .vbp = 0, | ||
| 314 | .x_res = width, | ||
| 315 | .y_res = height, | ||
| 316 | }; | ||
| 307 | 317 | ||
| 308 | /*BUG_ON(callback == 0);*/ | 318 | /*BUG_ON(callback == 0);*/ |
| 309 | BUG_ON(rfbi.framedone_callback != NULL); | 319 | BUG_ON(rfbi.framedone_callback != NULL); |
| 310 | 320 | ||
| 311 | DSSDBG("rfbi_transfer_area %dx%d\n", width, height); | 321 | DSSDBG("rfbi_transfer_area %dx%d\n", width, height); |
| 312 | 322 | ||
| 313 | dispc_mgr_set_lcd_size(dssdev->manager->id, width, height); | 323 | dss_mgr_set_timings(dssdev->manager, &timings); |
| 314 | 324 | ||
| 315 | dispc_mgr_enable(dssdev->manager->id, true); | 325 | dispc_mgr_enable(dssdev->manager->id, true); |
| 316 | 326 | ||
| @@ -766,6 +776,16 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, | |||
| 766 | u16 *x, u16 *y, u16 *w, u16 *h) | 776 | u16 *x, u16 *y, u16 *w, u16 *h) |
| 767 | { | 777 | { |
| 768 | u16 dw, dh; | 778 | u16 dw, dh; |
| 779 | struct omap_video_timings timings = { | ||
| 780 | .hsw = 1, | ||
| 781 | .hfp = 1, | ||
| 782 | .hbp = 1, | ||
| 783 | .vsw = 1, | ||
| 784 | .vfp = 0, | ||
| 785 | .vbp = 0, | ||
| 786 | .x_res = *w, | ||
| 787 | .y_res = *h, | ||
| 788 | }; | ||
| 769 | 789 | ||
| 770 | dssdev->driver->get_resolution(dssdev, &dw, &dh); | 790 | dssdev->driver->get_resolution(dssdev, &dw, &dh); |
| 771 | 791 | ||
| @@ -784,7 +804,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, | |||
| 784 | if (*w == 0 || *h == 0) | 804 | if (*w == 0 || *h == 0) |
| 785 | return -EINVAL; | 805 | return -EINVAL; |
| 786 | 806 | ||
| 787 | dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); | 807 | dss_mgr_set_timings(dssdev->manager, &timings); |
| 788 | 808 | ||
| 789 | return 0; | 809 | return 0; |
| 790 | } | 810 | } |
| @@ -799,7 +819,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev, | |||
| 799 | } | 819 | } |
| 800 | EXPORT_SYMBOL(omap_rfbi_update); | 820 | EXPORT_SYMBOL(omap_rfbi_update); |
| 801 | 821 | ||
| 802 | void rfbi_dump_regs(struct seq_file *s) | 822 | static void rfbi_dump_regs(struct seq_file *s) |
| 803 | { | 823 | { |
| 804 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) | 824 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) |
| 805 | 825 | ||
| @@ -900,15 +920,39 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) | |||
| 900 | } | 920 | } |
| 901 | EXPORT_SYMBOL(omapdss_rfbi_display_disable); | 921 | EXPORT_SYMBOL(omapdss_rfbi_display_disable); |
| 902 | 922 | ||
| 903 | int rfbi_init_display(struct omap_dss_device *dssdev) | 923 | static int __init rfbi_init_display(struct omap_dss_device *dssdev) |
| 904 | { | 924 | { |
| 905 | rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; | 925 | rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; |
| 906 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; | 926 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; |
| 907 | return 0; | 927 | return 0; |
| 908 | } | 928 | } |
| 909 | 929 | ||
| 930 | static void __init rfbi_probe_pdata(struct platform_device *pdev) | ||
| 931 | { | ||
| 932 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | ||
| 933 | int i, r; | ||
| 934 | |||
| 935 | for (i = 0; i < pdata->num_devices; ++i) { | ||
| 936 | struct omap_dss_device *dssdev = pdata->devices[i]; | ||
| 937 | |||
| 938 | if (dssdev->type != OMAP_DISPLAY_TYPE_DBI) | ||
| 939 | continue; | ||
| 940 | |||
| 941 | r = rfbi_init_display(dssdev); | ||
| 942 | if (r) { | ||
| 943 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | ||
| 944 | continue; | ||
| 945 | } | ||
| 946 | |||
| 947 | r = omap_dss_register_device(dssdev, &pdev->dev, i); | ||
| 948 | if (r) | ||
| 949 | DSSERR("device %s register failed: %d\n", | ||
| 950 | dssdev->name, r); | ||
| 951 | } | ||
| 952 | } | ||
| 953 | |||
| 910 | /* RFBI HW IP initialisation */ | 954 | /* RFBI HW IP initialisation */ |
| 911 | static int omap_rfbihw_probe(struct platform_device *pdev) | 955 | static int __init omap_rfbihw_probe(struct platform_device *pdev) |
| 912 | { | 956 | { |
| 913 | u32 rev; | 957 | u32 rev; |
| 914 | struct resource *rfbi_mem; | 958 | struct resource *rfbi_mem; |
| @@ -956,6 +1000,10 @@ static int omap_rfbihw_probe(struct platform_device *pdev) | |||
| 956 | 1000 | ||
| 957 | rfbi_runtime_put(); | 1001 | rfbi_runtime_put(); |
| 958 | 1002 | ||
| 1003 | dss_debugfs_create_file("rfbi", rfbi_dump_regs); | ||
| 1004 | |||
| 1005 | rfbi_probe_pdata(pdev); | ||
| 1006 | |||
| 959 | return 0; | 1007 | return 0; |
| 960 | 1008 | ||
| 961 | err_runtime_get: | 1009 | err_runtime_get: |
| @@ -963,8 +1011,9 @@ err_runtime_get: | |||
| 963 | return r; | 1011 | return r; |
| 964 | } | 1012 | } |
| 965 | 1013 | ||
| 966 | static int omap_rfbihw_remove(struct platform_device *pdev) | 1014 | static int __exit omap_rfbihw_remove(struct platform_device *pdev) |
| 967 | { | 1015 | { |
| 1016 | omap_dss_unregister_child_devices(&pdev->dev); | ||
| 968 | pm_runtime_disable(&pdev->dev); | 1017 | pm_runtime_disable(&pdev->dev); |
| 969 | return 0; | 1018 | return 0; |
| 970 | } | 1019 | } |
| @@ -972,7 +1021,6 @@ static int omap_rfbihw_remove(struct platform_device *pdev) | |||
| 972 | static int rfbi_runtime_suspend(struct device *dev) | 1021 | static int rfbi_runtime_suspend(struct device *dev) |
| 973 | { | 1022 | { |
| 974 | dispc_runtime_put(); | 1023 | dispc_runtime_put(); |
| 975 | dss_runtime_put(); | ||
| 976 | 1024 | ||
| 977 | return 0; | 1025 | return 0; |
| 978 | } | 1026 | } |
| @@ -981,20 +1029,11 @@ static int rfbi_runtime_resume(struct device *dev) | |||
| 981 | { | 1029 | { |
| 982 | int r; | 1030 | int r; |
| 983 | 1031 | ||
| 984 | r = dss_runtime_get(); | ||
| 985 | if (r < 0) | ||
| 986 | goto err_get_dss; | ||
| 987 | |||
| 988 | r = dispc_runtime_get(); | 1032 | r = dispc_runtime_get(); |
| 989 | if (r < 0) | 1033 | if (r < 0) |
| 990 | goto err_get_dispc; | 1034 | return r; |
| 991 | 1035 | ||
| 992 | return 0; | 1036 | return 0; |
| 993 | |||
| 994 | err_get_dispc: | ||
| 995 | dss_runtime_put(); | ||
| 996 | err_get_dss: | ||
| 997 | return r; | ||
| 998 | } | 1037 | } |
| 999 | 1038 | ||
| 1000 | static const struct dev_pm_ops rfbi_pm_ops = { | 1039 | static const struct dev_pm_ops rfbi_pm_ops = { |
| @@ -1003,8 +1042,7 @@ static const struct dev_pm_ops rfbi_pm_ops = { | |||
| 1003 | }; | 1042 | }; |
| 1004 | 1043 | ||
| 1005 | static struct platform_driver omap_rfbihw_driver = { | 1044 | static struct platform_driver omap_rfbihw_driver = { |
| 1006 | .probe = omap_rfbihw_probe, | 1045 | .remove = __exit_p(omap_rfbihw_remove), |
| 1007 | .remove = omap_rfbihw_remove, | ||
| 1008 | .driver = { | 1046 | .driver = { |
| 1009 | .name = "omapdss_rfbi", | 1047 | .name = "omapdss_rfbi", |
| 1010 | .owner = THIS_MODULE, | 1048 | .owner = THIS_MODULE, |
| @@ -1012,12 +1050,12 @@ static struct platform_driver omap_rfbihw_driver = { | |||
| 1012 | }, | 1050 | }, |
| 1013 | }; | 1051 | }; |
| 1014 | 1052 | ||
| 1015 | int rfbi_init_platform_driver(void) | 1053 | int __init rfbi_init_platform_driver(void) |
| 1016 | { | 1054 | { |
| 1017 | return platform_driver_register(&omap_rfbihw_driver); | 1055 | return platform_driver_probe(&omap_rfbihw_driver, omap_rfbihw_probe); |
| 1018 | } | 1056 | } |
| 1019 | 1057 | ||
| 1020 | void rfbi_uninit_platform_driver(void) | 1058 | void __exit rfbi_uninit_platform_driver(void) |
| 1021 | { | 1059 | { |
| 1022 | return platform_driver_unregister(&omap_rfbihw_driver); | 1060 | platform_driver_unregister(&omap_rfbihw_driver); |
| 1023 | } | 1061 | } |
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 8266ca0d666b..3a43dc2a9b46 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
| 25 | #include <linux/regulator/consumer.h> | 25 | #include <linux/regulator/consumer.h> |
| 26 | #include <linux/export.h> | 26 | #include <linux/export.h> |
| 27 | #include <linux/platform_device.h> | ||
| 27 | 28 | ||
| 28 | #include <video/omapdss.h> | 29 | #include <video/omapdss.h> |
| 29 | #include "dss.h" | 30 | #include "dss.h" |
| @@ -71,10 +72,6 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
| 71 | if (r) | 72 | if (r) |
| 72 | goto err_reg_enable; | 73 | goto err_reg_enable; |
| 73 | 74 | ||
| 74 | r = dss_runtime_get(); | ||
| 75 | if (r) | ||
| 76 | goto err_get_dss; | ||
| 77 | |||
| 78 | r = dispc_runtime_get(); | 75 | r = dispc_runtime_get(); |
| 79 | if (r) | 76 | if (r) |
| 80 | goto err_get_dispc; | 77 | goto err_get_dispc; |
| @@ -107,7 +104,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
| 107 | } | 104 | } |
| 108 | 105 | ||
| 109 | 106 | ||
| 110 | dispc_mgr_set_lcd_timings(dssdev->manager->id, t); | 107 | dss_mgr_set_timings(dssdev->manager, t); |
| 111 | 108 | ||
| 112 | r = dss_set_clock_div(&dss_cinfo); | 109 | r = dss_set_clock_div(&dss_cinfo); |
| 113 | if (r) | 110 | if (r) |
| @@ -137,8 +134,6 @@ err_set_dss_clock_div: | |||
| 137 | err_calc_clock_div: | 134 | err_calc_clock_div: |
| 138 | dispc_runtime_put(); | 135 | dispc_runtime_put(); |
| 139 | err_get_dispc: | 136 | err_get_dispc: |
| 140 | dss_runtime_put(); | ||
| 141 | err_get_dss: | ||
| 142 | regulator_disable(sdi.vdds_sdi_reg); | 137 | regulator_disable(sdi.vdds_sdi_reg); |
| 143 | err_reg_enable: | 138 | err_reg_enable: |
| 144 | omap_dss_stop_device(dssdev); | 139 | omap_dss_stop_device(dssdev); |
| @@ -154,7 +149,6 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) | |||
| 154 | dss_sdi_disable(); | 149 | dss_sdi_disable(); |
| 155 | 150 | ||
| 156 | dispc_runtime_put(); | 151 | dispc_runtime_put(); |
| 157 | dss_runtime_put(); | ||
| 158 | 152 | ||
| 159 | regulator_disable(sdi.vdds_sdi_reg); | 153 | regulator_disable(sdi.vdds_sdi_reg); |
| 160 | 154 | ||
| @@ -162,7 +156,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) | |||
| 162 | } | 156 | } |
| 163 | EXPORT_SYMBOL(omapdss_sdi_display_disable); | 157 | EXPORT_SYMBOL(omapdss_sdi_display_disable); |
| 164 | 158 | ||
| 165 | int sdi_init_display(struct omap_dss_device *dssdev) | 159 | static int __init sdi_init_display(struct omap_dss_device *dssdev) |
| 166 | { | 160 | { |
| 167 | DSSDBG("SDI init\n"); | 161 | DSSDBG("SDI init\n"); |
| 168 | 162 | ||
| @@ -182,11 +176,58 @@ int sdi_init_display(struct omap_dss_device *dssdev) | |||
| 182 | return 0; | 176 | return 0; |
| 183 | } | 177 | } |
| 184 | 178 | ||
| 185 | int sdi_init(void) | 179 | static void __init sdi_probe_pdata(struct platform_device *pdev) |
| 180 | { | ||
| 181 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | ||
| 182 | int i, r; | ||
| 183 | |||
| 184 | for (i = 0; i < pdata->num_devices; ++i) { | ||
| 185 | struct omap_dss_device *dssdev = pdata->devices[i]; | ||
| 186 | |||
| 187 | if (dssdev->type != OMAP_DISPLAY_TYPE_SDI) | ||
| 188 | continue; | ||
| 189 | |||
| 190 | r = sdi_init_display(dssdev); | ||
| 191 | if (r) { | ||
| 192 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | ||
| 193 | continue; | ||
| 194 | } | ||
| 195 | |||
| 196 | r = omap_dss_register_device(dssdev, &pdev->dev, i); | ||
| 197 | if (r) | ||
| 198 | DSSERR("device %s register failed: %d\n", | ||
| 199 | dssdev->name, r); | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | static int __init omap_sdi_probe(struct platform_device *pdev) | ||
| 186 | { | 204 | { |
| 205 | sdi_probe_pdata(pdev); | ||
| 206 | |||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | static int __exit omap_sdi_remove(struct platform_device *pdev) | ||
| 211 | { | ||
| 212 | omap_dss_unregister_child_devices(&pdev->dev); | ||
| 213 | |||
| 187 | return 0; | 214 | return 0; |
| 188 | } | 215 | } |
| 189 | 216 | ||
| 190 | void sdi_exit(void) | 217 | static struct platform_driver omap_sdi_driver = { |
| 218 | .remove = __exit_p(omap_sdi_remove), | ||
| 219 | .driver = { | ||
| 220 | .name = "omapdss_sdi", | ||
| 221 | .owner = THIS_MODULE, | ||
| 222 | }, | ||
| 223 | }; | ||
| 224 | |||
| 225 | int __init sdi_init_platform_driver(void) | ||
| 226 | { | ||
| 227 | return platform_driver_probe(&omap_sdi_driver, omap_sdi_probe); | ||
| 228 | } | ||
| 229 | |||
| 230 | void __exit sdi_uninit_platform_driver(void) | ||
| 191 | { | 231 | { |
| 232 | platform_driver_unregister(&omap_sdi_driver); | ||
| 192 | } | 233 | } |
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h index 1f58b84d6901..e734cb444bc7 100644 --- a/drivers/video/omap2/dss/ti_hdmi.h +++ b/drivers/video/omap2/dss/ti_hdmi.h | |||
| @@ -96,7 +96,9 @@ struct ti_hdmi_ip_ops { | |||
| 96 | 96 | ||
| 97 | void (*pll_disable)(struct hdmi_ip_data *ip_data); | 97 | void (*pll_disable)(struct hdmi_ip_data *ip_data); |
| 98 | 98 | ||
| 99 | void (*video_enable)(struct hdmi_ip_data *ip_data, bool start); | 99 | int (*video_enable)(struct hdmi_ip_data *ip_data); |
| 100 | |||
| 101 | void (*video_disable)(struct hdmi_ip_data *ip_data); | ||
| 100 | 102 | ||
| 101 | void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s); | 103 | void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s); |
| 102 | 104 | ||
| @@ -106,9 +108,17 @@ struct ti_hdmi_ip_ops { | |||
| 106 | 108 | ||
| 107 | void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s); | 109 | void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s); |
| 108 | 110 | ||
| 109 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 111 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) |
| 110 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | 112 | int (*audio_enable)(struct hdmi_ip_data *ip_data); |
| 111 | void (*audio_enable)(struct hdmi_ip_data *ip_data, bool start); | 113 | |
| 114 | void (*audio_disable)(struct hdmi_ip_data *ip_data); | ||
| 115 | |||
| 116 | int (*audio_start)(struct hdmi_ip_data *ip_data); | ||
| 117 | |||
| 118 | void (*audio_stop)(struct hdmi_ip_data *ip_data); | ||
| 119 | |||
| 120 | int (*audio_config)(struct hdmi_ip_data *ip_data, | ||
| 121 | struct omap_dss_audio *audio); | ||
| 112 | #endif | 122 | #endif |
| 113 | 123 | ||
| 114 | }; | 124 | }; |
| @@ -173,7 +183,8 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data); | |||
| 173 | void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); | 183 | void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); |
| 174 | int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len); | 184 | int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len); |
| 175 | bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data); | 185 | bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data); |
| 176 | void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start); | 186 | int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data); |
| 187 | void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data); | ||
| 177 | int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); | 188 | int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); |
| 178 | void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); | 189 | void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); |
| 179 | void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data); | 190 | void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data); |
| @@ -181,8 +192,13 @@ void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | |||
| 181 | void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | 192 | void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); |
| 182 | void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | 193 | void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); |
| 183 | void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | 194 | void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); |
| 184 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 195 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) |
| 185 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | 196 | int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts); |
| 186 | void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable); | 197 | int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data); |
| 198 | void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data); | ||
| 199 | int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data); | ||
| 200 | void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data); | ||
| 201 | int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, | ||
| 202 | struct omap_dss_audio *audio); | ||
| 187 | #endif | 203 | #endif |
| 188 | #endif | 204 | #endif |
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index bfe6fe65c8be..4dae1b291079 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | |||
| @@ -29,9 +29,14 @@ | |||
| 29 | #include <linux/string.h> | 29 | #include <linux/string.h> |
| 30 | #include <linux/seq_file.h> | 30 | #include <linux/seq_file.h> |
| 31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
| 32 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) | ||
| 33 | #include <sound/asound.h> | ||
| 34 | #include <sound/asoundef.h> | ||
| 35 | #endif | ||
| 32 | 36 | ||
| 33 | #include "ti_hdmi_4xxx_ip.h" | 37 | #include "ti_hdmi_4xxx_ip.h" |
| 34 | #include "dss.h" | 38 | #include "dss.h" |
| 39 | #include "dss_features.h" | ||
| 35 | 40 | ||
| 36 | static inline void hdmi_write_reg(void __iomem *base_addr, | 41 | static inline void hdmi_write_reg(void __iomem *base_addr, |
| 37 | const u16 idx, u32 val) | 42 | const u16 idx, u32 val) |
| @@ -298,9 +303,9 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data) | |||
| 298 | REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); | 303 | REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); |
| 299 | 304 | ||
| 300 | r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio), | 305 | r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio), |
| 301 | NULL, hpd_irq_handler, | 306 | NULL, hpd_irq_handler, |
| 302 | IRQF_DISABLED | IRQF_TRIGGER_RISING | | 307 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | |
| 303 | IRQF_TRIGGER_FALLING, "hpd", ip_data); | 308 | IRQF_ONESHOT, "hpd", ip_data); |
| 304 | if (r) { | 309 | if (r) { |
| 305 | DSSERR("HPD IRQ request failed\n"); | 310 | DSSERR("HPD IRQ request failed\n"); |
| 306 | hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); | 311 | hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); |
| @@ -699,9 +704,15 @@ static void hdmi_wp_init(struct omap_video_timings *timings, | |||
| 699 | 704 | ||
| 700 | } | 705 | } |
| 701 | 706 | ||
| 702 | void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start) | 707 | int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data) |
| 708 | { | ||
| 709 | REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, true, 31, 31); | ||
| 710 | return 0; | ||
| 711 | } | ||
| 712 | |||
| 713 | void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data) | ||
| 703 | { | 714 | { |
| 704 | REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31); | 715 | REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, false, 31, 31); |
| 705 | } | 716 | } |
| 706 | 717 | ||
| 707 | static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, | 718 | static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, |
| @@ -886,10 +897,12 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | |||
| 886 | 897 | ||
| 887 | #define CORE_REG(i, name) name(i) | 898 | #define CORE_REG(i, name) name(i) |
| 888 | #define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\ | 899 | #define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\ |
| 889 | hdmi_read_reg(hdmi_pll_base(ip_data), r)) | 900 | hdmi_read_reg(hdmi_core_sys_base(ip_data), r)) |
| 890 | #define DUMPCOREAV(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ | 901 | #define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\ |
| 902 | hdmi_read_reg(hdmi_av_base(ip_data), r)) | ||
| 903 | #define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ | ||
| 891 | (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \ | 904 | (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \ |
| 892 | hdmi_read_reg(hdmi_pll_base(ip_data), CORE_REG(i, r))) | 905 | hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r))) |
| 893 | 906 | ||
| 894 | DUMPCORE(HDMI_CORE_SYS_VND_IDL); | 907 | DUMPCORE(HDMI_CORE_SYS_VND_IDL); |
| 895 | DUMPCORE(HDMI_CORE_SYS_DEV_IDL); | 908 | DUMPCORE(HDMI_CORE_SYS_DEV_IDL); |
| @@ -898,6 +911,13 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | |||
| 898 | DUMPCORE(HDMI_CORE_SYS_SRST); | 911 | DUMPCORE(HDMI_CORE_SYS_SRST); |
| 899 | DUMPCORE(HDMI_CORE_CTRL1); | 912 | DUMPCORE(HDMI_CORE_CTRL1); |
| 900 | DUMPCORE(HDMI_CORE_SYS_SYS_STAT); | 913 | DUMPCORE(HDMI_CORE_SYS_SYS_STAT); |
| 914 | DUMPCORE(HDMI_CORE_SYS_DE_DLY); | ||
| 915 | DUMPCORE(HDMI_CORE_SYS_DE_CTRL); | ||
| 916 | DUMPCORE(HDMI_CORE_SYS_DE_TOP); | ||
| 917 | DUMPCORE(HDMI_CORE_SYS_DE_CNTL); | ||
| 918 | DUMPCORE(HDMI_CORE_SYS_DE_CNTH); | ||
| 919 | DUMPCORE(HDMI_CORE_SYS_DE_LINL); | ||
| 920 | DUMPCORE(HDMI_CORE_SYS_DE_LINH_1); | ||
| 901 | DUMPCORE(HDMI_CORE_SYS_VID_ACEN); | 921 | DUMPCORE(HDMI_CORE_SYS_VID_ACEN); |
| 902 | DUMPCORE(HDMI_CORE_SYS_VID_MODE); | 922 | DUMPCORE(HDMI_CORE_SYS_VID_MODE); |
| 903 | DUMPCORE(HDMI_CORE_SYS_INTR_STATE); | 923 | DUMPCORE(HDMI_CORE_SYS_INTR_STATE); |
| @@ -907,102 +927,91 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | |||
| 907 | DUMPCORE(HDMI_CORE_SYS_INTR4); | 927 | DUMPCORE(HDMI_CORE_SYS_INTR4); |
| 908 | DUMPCORE(HDMI_CORE_SYS_UMASK1); | 928 | DUMPCORE(HDMI_CORE_SYS_UMASK1); |
| 909 | DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL); | 929 | DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL); |
| 910 | DUMPCORE(HDMI_CORE_SYS_DE_DLY); | ||
| 911 | DUMPCORE(HDMI_CORE_SYS_DE_CTRL); | ||
| 912 | DUMPCORE(HDMI_CORE_SYS_DE_TOP); | ||
| 913 | DUMPCORE(HDMI_CORE_SYS_DE_CNTL); | ||
| 914 | DUMPCORE(HDMI_CORE_SYS_DE_CNTH); | ||
| 915 | DUMPCORE(HDMI_CORE_SYS_DE_LINL); | ||
| 916 | DUMPCORE(HDMI_CORE_SYS_DE_LINH_1); | ||
| 917 | 930 | ||
| 918 | DUMPCORE(HDMI_CORE_DDC_CMD); | ||
| 919 | DUMPCORE(HDMI_CORE_DDC_STATUS); | ||
| 920 | DUMPCORE(HDMI_CORE_DDC_ADDR); | 931 | DUMPCORE(HDMI_CORE_DDC_ADDR); |
| 932 | DUMPCORE(HDMI_CORE_DDC_SEGM); | ||
| 921 | DUMPCORE(HDMI_CORE_DDC_OFFSET); | 933 | DUMPCORE(HDMI_CORE_DDC_OFFSET); |
| 922 | DUMPCORE(HDMI_CORE_DDC_COUNT1); | 934 | DUMPCORE(HDMI_CORE_DDC_COUNT1); |
| 923 | DUMPCORE(HDMI_CORE_DDC_COUNT2); | 935 | DUMPCORE(HDMI_CORE_DDC_COUNT2); |
| 936 | DUMPCORE(HDMI_CORE_DDC_STATUS); | ||
| 937 | DUMPCORE(HDMI_CORE_DDC_CMD); | ||
| 924 | DUMPCORE(HDMI_CORE_DDC_DATA); | 938 | DUMPCORE(HDMI_CORE_DDC_DATA); |
| 925 | DUMPCORE(HDMI_CORE_DDC_SEGM); | ||
| 926 | 939 | ||
| 927 | DUMPCORE(HDMI_CORE_AV_HDMI_CTRL); | 940 | DUMPCOREAV(HDMI_CORE_AV_ACR_CTRL); |
| 928 | DUMPCORE(HDMI_CORE_AV_DPD); | 941 | DUMPCOREAV(HDMI_CORE_AV_FREQ_SVAL); |
| 929 | DUMPCORE(HDMI_CORE_AV_PB_CTRL1); | 942 | DUMPCOREAV(HDMI_CORE_AV_N_SVAL1); |
| 930 | DUMPCORE(HDMI_CORE_AV_PB_CTRL2); | 943 | DUMPCOREAV(HDMI_CORE_AV_N_SVAL2); |
| 931 | DUMPCORE(HDMI_CORE_AV_AVI_TYPE); | 944 | DUMPCOREAV(HDMI_CORE_AV_N_SVAL3); |
| 932 | DUMPCORE(HDMI_CORE_AV_AVI_VERS); | 945 | DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL1); |
| 933 | DUMPCORE(HDMI_CORE_AV_AVI_LEN); | 946 | DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL2); |
| 934 | DUMPCORE(HDMI_CORE_AV_AVI_CHSUM); | 947 | DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL3); |
| 948 | DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL1); | ||
| 949 | DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL2); | ||
| 950 | DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL3); | ||
| 951 | DUMPCOREAV(HDMI_CORE_AV_AUD_MODE); | ||
| 952 | DUMPCOREAV(HDMI_CORE_AV_SPDIF_CTRL); | ||
| 953 | DUMPCOREAV(HDMI_CORE_AV_HW_SPDIF_FS); | ||
| 954 | DUMPCOREAV(HDMI_CORE_AV_SWAP_I2S); | ||
| 955 | DUMPCOREAV(HDMI_CORE_AV_SPDIF_ERTH); | ||
| 956 | DUMPCOREAV(HDMI_CORE_AV_I2S_IN_MAP); | ||
| 957 | DUMPCOREAV(HDMI_CORE_AV_I2S_IN_CTRL); | ||
| 958 | DUMPCOREAV(HDMI_CORE_AV_I2S_CHST0); | ||
| 959 | DUMPCOREAV(HDMI_CORE_AV_I2S_CHST1); | ||
| 960 | DUMPCOREAV(HDMI_CORE_AV_I2S_CHST2); | ||
| 961 | DUMPCOREAV(HDMI_CORE_AV_I2S_CHST4); | ||
| 962 | DUMPCOREAV(HDMI_CORE_AV_I2S_CHST5); | ||
| 963 | DUMPCOREAV(HDMI_CORE_AV_ASRC); | ||
| 964 | DUMPCOREAV(HDMI_CORE_AV_I2S_IN_LEN); | ||
| 965 | DUMPCOREAV(HDMI_CORE_AV_HDMI_CTRL); | ||
| 966 | DUMPCOREAV(HDMI_CORE_AV_AUDO_TXSTAT); | ||
| 967 | DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_1); | ||
| 968 | DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_2); | ||
| 969 | DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_3); | ||
| 970 | DUMPCOREAV(HDMI_CORE_AV_TEST_TXCTRL); | ||
| 971 | DUMPCOREAV(HDMI_CORE_AV_DPD); | ||
| 972 | DUMPCOREAV(HDMI_CORE_AV_PB_CTRL1); | ||
| 973 | DUMPCOREAV(HDMI_CORE_AV_PB_CTRL2); | ||
| 974 | DUMPCOREAV(HDMI_CORE_AV_AVI_TYPE); | ||
| 975 | DUMPCOREAV(HDMI_CORE_AV_AVI_VERS); | ||
| 976 | DUMPCOREAV(HDMI_CORE_AV_AVI_LEN); | ||
| 977 | DUMPCOREAV(HDMI_CORE_AV_AVI_CHSUM); | ||
| 935 | 978 | ||
| 936 | for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++) | 979 | for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++) |
| 937 | DUMPCOREAV(i, HDMI_CORE_AV_AVI_DBYTE); | 980 | DUMPCOREAV2(i, HDMI_CORE_AV_AVI_DBYTE); |
| 981 | |||
| 982 | DUMPCOREAV(HDMI_CORE_AV_SPD_TYPE); | ||
| 983 | DUMPCOREAV(HDMI_CORE_AV_SPD_VERS); | ||
| 984 | DUMPCOREAV(HDMI_CORE_AV_SPD_LEN); | ||
| 985 | DUMPCOREAV(HDMI_CORE_AV_SPD_CHSUM); | ||
| 938 | 986 | ||
| 939 | for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++) | 987 | for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++) |
| 940 | DUMPCOREAV(i, HDMI_CORE_AV_SPD_DBYTE); | 988 | DUMPCOREAV2(i, HDMI_CORE_AV_SPD_DBYTE); |
| 989 | |||
| 990 | DUMPCOREAV(HDMI_CORE_AV_AUDIO_TYPE); | ||
| 991 | DUMPCOREAV(HDMI_CORE_AV_AUDIO_VERS); | ||
| 992 | DUMPCOREAV(HDMI_CORE_AV_AUDIO_LEN); | ||
| 993 | DUMPCOREAV(HDMI_CORE_AV_AUDIO_CHSUM); | ||
| 941 | 994 | ||
| 942 | for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++) | 995 | for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++) |
| 943 | DUMPCOREAV(i, HDMI_CORE_AV_AUD_DBYTE); | 996 | DUMPCOREAV2(i, HDMI_CORE_AV_AUD_DBYTE); |
| 997 | |||
| 998 | DUMPCOREAV(HDMI_CORE_AV_MPEG_TYPE); | ||
| 999 | DUMPCOREAV(HDMI_CORE_AV_MPEG_VERS); | ||
| 1000 | DUMPCOREAV(HDMI_CORE_AV_MPEG_LEN); | ||
| 1001 | DUMPCOREAV(HDMI_CORE_AV_MPEG_CHSUM); | ||
| 944 | 1002 | ||
| 945 | for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++) | 1003 | for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++) |
| 946 | DUMPCOREAV(i, HDMI_CORE_AV_MPEG_DBYTE); | 1004 | DUMPCOREAV2(i, HDMI_CORE_AV_MPEG_DBYTE); |
| 947 | 1005 | ||
| 948 | for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++) | 1006 | for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++) |
| 949 | DUMPCOREAV(i, HDMI_CORE_AV_GEN_DBYTE); | 1007 | DUMPCOREAV2(i, HDMI_CORE_AV_GEN_DBYTE); |
| 1008 | |||
| 1009 | DUMPCOREAV(HDMI_CORE_AV_CP_BYTE1); | ||
| 950 | 1010 | ||
| 951 | for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++) | 1011 | for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++) |
| 952 | DUMPCOREAV(i, HDMI_CORE_AV_GEN2_DBYTE); | 1012 | DUMPCOREAV2(i, HDMI_CORE_AV_GEN2_DBYTE); |
| 953 | 1013 | ||
| 954 | DUMPCORE(HDMI_CORE_AV_ACR_CTRL); | 1014 | DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID); |
| 955 | DUMPCORE(HDMI_CORE_AV_FREQ_SVAL); | ||
| 956 | DUMPCORE(HDMI_CORE_AV_N_SVAL1); | ||
| 957 | DUMPCORE(HDMI_CORE_AV_N_SVAL2); | ||
| 958 | DUMPCORE(HDMI_CORE_AV_N_SVAL3); | ||
| 959 | DUMPCORE(HDMI_CORE_AV_CTS_SVAL1); | ||
| 960 | DUMPCORE(HDMI_CORE_AV_CTS_SVAL2); | ||
| 961 | DUMPCORE(HDMI_CORE_AV_CTS_SVAL3); | ||
| 962 | DUMPCORE(HDMI_CORE_AV_CTS_HVAL1); | ||
| 963 | DUMPCORE(HDMI_CORE_AV_CTS_HVAL2); | ||
| 964 | DUMPCORE(HDMI_CORE_AV_CTS_HVAL3); | ||
| 965 | DUMPCORE(HDMI_CORE_AV_AUD_MODE); | ||
| 966 | DUMPCORE(HDMI_CORE_AV_SPDIF_CTRL); | ||
| 967 | DUMPCORE(HDMI_CORE_AV_HW_SPDIF_FS); | ||
| 968 | DUMPCORE(HDMI_CORE_AV_SWAP_I2S); | ||
| 969 | DUMPCORE(HDMI_CORE_AV_SPDIF_ERTH); | ||
| 970 | DUMPCORE(HDMI_CORE_AV_I2S_IN_MAP); | ||
| 971 | DUMPCORE(HDMI_CORE_AV_I2S_IN_CTRL); | ||
| 972 | DUMPCORE(HDMI_CORE_AV_I2S_CHST0); | ||
| 973 | DUMPCORE(HDMI_CORE_AV_I2S_CHST1); | ||
| 974 | DUMPCORE(HDMI_CORE_AV_I2S_CHST2); | ||
| 975 | DUMPCORE(HDMI_CORE_AV_I2S_CHST4); | ||
| 976 | DUMPCORE(HDMI_CORE_AV_I2S_CHST5); | ||
| 977 | DUMPCORE(HDMI_CORE_AV_ASRC); | ||
| 978 | DUMPCORE(HDMI_CORE_AV_I2S_IN_LEN); | ||
| 979 | DUMPCORE(HDMI_CORE_AV_HDMI_CTRL); | ||
| 980 | DUMPCORE(HDMI_CORE_AV_AUDO_TXSTAT); | ||
| 981 | DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_1); | ||
| 982 | DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_2); | ||
| 983 | DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_3); | ||
| 984 | DUMPCORE(HDMI_CORE_AV_TEST_TXCTRL); | ||
| 985 | DUMPCORE(HDMI_CORE_AV_DPD); | ||
| 986 | DUMPCORE(HDMI_CORE_AV_PB_CTRL1); | ||
| 987 | DUMPCORE(HDMI_CORE_AV_PB_CTRL2); | ||
| 988 | DUMPCORE(HDMI_CORE_AV_AVI_TYPE); | ||
| 989 | DUMPCORE(HDMI_CORE_AV_AVI_VERS); | ||
| 990 | DUMPCORE(HDMI_CORE_AV_AVI_LEN); | ||
| 991 | DUMPCORE(HDMI_CORE_AV_AVI_CHSUM); | ||
| 992 | DUMPCORE(HDMI_CORE_AV_SPD_TYPE); | ||
| 993 | DUMPCORE(HDMI_CORE_AV_SPD_VERS); | ||
| 994 | DUMPCORE(HDMI_CORE_AV_SPD_LEN); | ||
| 995 | DUMPCORE(HDMI_CORE_AV_SPD_CHSUM); | ||
| 996 | DUMPCORE(HDMI_CORE_AV_AUDIO_TYPE); | ||
| 997 | DUMPCORE(HDMI_CORE_AV_AUDIO_VERS); | ||
| 998 | DUMPCORE(HDMI_CORE_AV_AUDIO_LEN); | ||
| 999 | DUMPCORE(HDMI_CORE_AV_AUDIO_CHSUM); | ||
| 1000 | DUMPCORE(HDMI_CORE_AV_MPEG_TYPE); | ||
| 1001 | DUMPCORE(HDMI_CORE_AV_MPEG_VERS); | ||
| 1002 | DUMPCORE(HDMI_CORE_AV_MPEG_LEN); | ||
| 1003 | DUMPCORE(HDMI_CORE_AV_MPEG_CHSUM); | ||
| 1004 | DUMPCORE(HDMI_CORE_AV_CP_BYTE1); | ||
| 1005 | DUMPCORE(HDMI_CORE_AV_CEC_ADDR_ID); | ||
| 1006 | } | 1015 | } |
| 1007 | 1016 | ||
| 1008 | void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | 1017 | void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) |
| @@ -1016,9 +1025,8 @@ void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | |||
| 1016 | DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); | 1025 | DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); |
| 1017 | } | 1026 | } |
| 1018 | 1027 | ||
| 1019 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 1028 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) |
| 1020 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | 1029 | static void ti_hdmi_4xxx_wp_audio_config_format(struct hdmi_ip_data *ip_data, |
| 1021 | void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data, | ||
| 1022 | struct hdmi_audio_format *aud_fmt) | 1030 | struct hdmi_audio_format *aud_fmt) |
| 1023 | { | 1031 | { |
| 1024 | u32 r; | 1032 | u32 r; |
| @@ -1037,7 +1045,7 @@ void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data, | |||
| 1037 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r); | 1045 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r); |
| 1038 | } | 1046 | } |
| 1039 | 1047 | ||
| 1040 | void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data, | 1048 | static void ti_hdmi_4xxx_wp_audio_config_dma(struct hdmi_ip_data *ip_data, |
| 1041 | struct hdmi_audio_dma *aud_dma) | 1049 | struct hdmi_audio_dma *aud_dma) |
| 1042 | { | 1050 | { |
| 1043 | u32 r; | 1051 | u32 r; |
| @@ -1055,7 +1063,7 @@ void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data, | |||
| 1055 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r); | 1063 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r); |
| 1056 | } | 1064 | } |
| 1057 | 1065 | ||
| 1058 | void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, | 1066 | static void ti_hdmi_4xxx_core_audio_config(struct hdmi_ip_data *ip_data, |
| 1059 | struct hdmi_core_audio_config *cfg) | 1067 | struct hdmi_core_audio_config *cfg) |
| 1060 | { | 1068 | { |
| 1061 | u32 r; | 1069 | u32 r; |
| @@ -1106,27 +1114,33 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, | |||
| 1106 | REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL, | 1114 | REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL, |
| 1107 | cfg->fs_override, 1, 1); | 1115 | cfg->fs_override, 1, 1); |
| 1108 | 1116 | ||
| 1109 | /* I2S parameters */ | 1117 | /* |
| 1110 | REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_CHST4, | 1118 | * Set IEC-60958-3 channel status word. It is passed to the IP |
| 1111 | cfg->freq_sample, 3, 0); | 1119 | * just as it is received. The user of the driver is responsible |
| 1112 | 1120 | * for its contents. | |
| 1121 | */ | ||
| 1122 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST0, | ||
| 1123 | cfg->iec60958_cfg->status[0]); | ||
| 1124 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST1, | ||
| 1125 | cfg->iec60958_cfg->status[1]); | ||
| 1126 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST2, | ||
| 1127 | cfg->iec60958_cfg->status[2]); | ||
| 1128 | /* yes, this is correct: status[3] goes to CHST4 register */ | ||
| 1129 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST4, | ||
| 1130 | cfg->iec60958_cfg->status[3]); | ||
| 1131 | /* yes, this is correct: status[4] goes to CHST5 register */ | ||
| 1132 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, | ||
| 1133 | cfg->iec60958_cfg->status[4]); | ||
| 1134 | |||
| 1135 | /* set I2S parameters */ | ||
| 1113 | r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL); | 1136 | r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL); |
| 1114 | r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7); | ||
| 1115 | r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); | 1137 | r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); |
| 1116 | r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5); | ||
| 1117 | r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); | 1138 | r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); |
| 1118 | r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3); | ||
| 1119 | r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); | 1139 | r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); |
| 1120 | r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); | 1140 | r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); |
| 1121 | r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); | 1141 | r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); |
| 1122 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r); | 1142 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r); |
| 1123 | 1143 | ||
| 1124 | r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_CHST5); | ||
| 1125 | r = FLD_MOD(r, cfg->freq_sample, 7, 4); | ||
| 1126 | r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1); | ||
| 1127 | r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0); | ||
| 1128 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, r); | ||
| 1129 | |||
| 1130 | REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN, | 1144 | REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN, |
| 1131 | cfg->i2s_cfg.in_length_bits, 3, 0); | 1145 | cfg->i2s_cfg.in_length_bits, 3, 0); |
| 1132 | 1146 | ||
| @@ -1138,12 +1152,19 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, | |||
| 1138 | r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); | 1152 | r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); |
| 1139 | r = FLD_MOD(r, cfg->en_spdif, 1, 1); | 1153 | r = FLD_MOD(r, cfg->en_spdif, 1, 1); |
| 1140 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r); | 1154 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r); |
| 1155 | |||
| 1156 | /* Audio channel mappings */ | ||
| 1157 | /* TODO: Make channel mapping dynamic. For now, map channels | ||
| 1158 | * in the ALSA order: FL/FR/RL/RR/C/LFE/SL/SR. Remapping is needed as | ||
| 1159 | * HDMI speaker order is different. See CEA-861 Section 6.6.2. | ||
| 1160 | */ | ||
| 1161 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_MAP, 0x78); | ||
| 1162 | REG_FLD_MOD(av_base, HDMI_CORE_AV_SWAP_I2S, 1, 5, 5); | ||
| 1141 | } | 1163 | } |
| 1142 | 1164 | ||
| 1143 | void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, | 1165 | static void ti_hdmi_4xxx_core_audio_infoframe_cfg(struct hdmi_ip_data *ip_data, |
| 1144 | struct hdmi_core_infoframe_audio *info_aud) | 1166 | struct snd_cea_861_aud_if *info_aud) |
| 1145 | { | 1167 | { |
| 1146 | u8 val; | ||
| 1147 | u8 sum = 0, checksum = 0; | 1168 | u8 sum = 0, checksum = 0; |
| 1148 | void __iomem *av_base = hdmi_av_base(ip_data); | 1169 | void __iomem *av_base = hdmi_av_base(ip_data); |
| 1149 | 1170 | ||
| @@ -1157,24 +1178,23 @@ void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, | |||
| 1157 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a); | 1178 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a); |
| 1158 | sum += 0x84 + 0x001 + 0x00a; | 1179 | sum += 0x84 + 0x001 + 0x00a; |
| 1159 | 1180 | ||
| 1160 | val = (info_aud->db1_coding_type << 4) | 1181 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), |
| 1161 | | (info_aud->db1_channel_count - 1); | 1182 | info_aud->db1_ct_cc); |
| 1162 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), val); | 1183 | sum += info_aud->db1_ct_cc; |
| 1163 | sum += val; | ||
| 1164 | 1184 | ||
| 1165 | val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; | 1185 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), |
| 1166 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), val); | 1186 | info_aud->db2_sf_ss); |
| 1167 | sum += val; | 1187 | sum += info_aud->db2_sf_ss; |
| 1168 | 1188 | ||
| 1169 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), 0x00); | 1189 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3); |
| 1190 | sum += info_aud->db3; | ||
| 1170 | 1191 | ||
| 1171 | val = info_aud->db4_channel_alloc; | 1192 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca); |
| 1172 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), val); | 1193 | sum += info_aud->db4_ca; |
| 1173 | sum += val; | ||
| 1174 | 1194 | ||
| 1175 | val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); | 1195 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), |
| 1176 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), val); | 1196 | info_aud->db5_dminh_lsv); |
| 1177 | sum += val; | 1197 | sum += info_aud->db5_dminh_lsv; |
| 1178 | 1198 | ||
| 1179 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00); | 1199 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00); |
| 1180 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00); | 1200 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00); |
| @@ -1192,70 +1212,212 @@ void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, | |||
| 1192 | */ | 1212 | */ |
| 1193 | } | 1213 | } |
| 1194 | 1214 | ||
| 1195 | int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, | 1215 | int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, |
| 1196 | u32 sample_freq, u32 *n, u32 *cts) | 1216 | struct omap_dss_audio *audio) |
| 1197 | { | 1217 | { |
| 1198 | u32 r; | 1218 | struct hdmi_audio_format audio_format; |
| 1199 | u32 deep_color = 0; | 1219 | struct hdmi_audio_dma audio_dma; |
| 1200 | u32 pclk = ip_data->cfg.timings.pixel_clock; | 1220 | struct hdmi_core_audio_config core; |
| 1201 | 1221 | int err, n, cts, channel_count; | |
| 1202 | if (n == NULL || cts == NULL) | 1222 | unsigned int fs_nr; |
| 1223 | bool word_length_16b = false; | ||
| 1224 | |||
| 1225 | if (!audio || !audio->iec || !audio->cea || !ip_data) | ||
| 1203 | return -EINVAL; | 1226 | return -EINVAL; |
| 1227 | |||
| 1228 | core.iec60958_cfg = audio->iec; | ||
| 1204 | /* | 1229 | /* |
| 1205 | * Obtain current deep color configuration. This needed | 1230 | * In the IEC-60958 status word, check if the audio sample word length |
| 1206 | * to calculate the TMDS clock based on the pixel clock. | 1231 | * is 16-bit as several optimizations can be performed in such case. |
| 1207 | */ | 1232 | */ |
| 1208 | r = REG_GET(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, 1, 0); | 1233 | if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24)) |
| 1209 | switch (r) { | 1234 | if (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16) |
| 1210 | case 1: /* No deep color selected */ | 1235 | word_length_16b = true; |
| 1211 | deep_color = 100; | 1236 | |
| 1237 | /* I2S configuration. See Phillips' specification */ | ||
| 1238 | if (word_length_16b) | ||
| 1239 | core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT; | ||
| 1240 | else | ||
| 1241 | core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT; | ||
| 1242 | /* | ||
| 1243 | * The I2S input word length is twice the lenght given in the IEC-60958 | ||
| 1244 | * status word. If the word size is greater than | ||
| 1245 | * 20 bits, increment by one. | ||
| 1246 | */ | ||
| 1247 | core.i2s_cfg.in_length_bits = audio->iec->status[4] | ||
| 1248 | & IEC958_AES4_CON_WORDLEN; | ||
| 1249 | if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24) | ||
| 1250 | core.i2s_cfg.in_length_bits++; | ||
| 1251 | core.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING; | ||
| 1252 | core.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM; | ||
| 1253 | core.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST; | ||
| 1254 | core.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT; | ||
| 1255 | |||
| 1256 | /* convert sample frequency to a number */ | ||
| 1257 | switch (audio->iec->status[3] & IEC958_AES3_CON_FS) { | ||
| 1258 | case IEC958_AES3_CON_FS_32000: | ||
| 1259 | fs_nr = 32000; | ||
| 1260 | break; | ||
| 1261 | case IEC958_AES3_CON_FS_44100: | ||
| 1262 | fs_nr = 44100; | ||
| 1263 | break; | ||
| 1264 | case IEC958_AES3_CON_FS_48000: | ||
| 1265 | fs_nr = 48000; | ||
| 1212 | break; | 1266 | break; |
| 1213 | case 2: /* 10-bit deep color selected */ | 1267 | case IEC958_AES3_CON_FS_88200: |
| 1214 | deep_color = 125; | 1268 | fs_nr = 88200; |
| 1215 | break; | 1269 | break; |
| 1216 | case 3: /* 12-bit deep color selected */ | 1270 | case IEC958_AES3_CON_FS_96000: |
| 1217 | deep_color = 150; | 1271 | fs_nr = 96000; |
| 1272 | break; | ||
| 1273 | case IEC958_AES3_CON_FS_176400: | ||
| 1274 | fs_nr = 176400; | ||
| 1275 | break; | ||
| 1276 | case IEC958_AES3_CON_FS_192000: | ||
| 1277 | fs_nr = 192000; | ||
| 1218 | break; | 1278 | break; |
| 1219 | default: | 1279 | default: |
| 1220 | return -EINVAL; | 1280 | return -EINVAL; |
| 1221 | } | 1281 | } |
| 1222 | 1282 | ||
| 1223 | switch (sample_freq) { | 1283 | err = hdmi_compute_acr(fs_nr, &n, &cts); |
| 1224 | case 32000: | 1284 | |
| 1225 | if ((deep_color == 125) && ((pclk == 54054) | 1285 | /* Audio clock regeneration settings */ |
| 1226 | || (pclk == 74250))) | 1286 | core.n = n; |
| 1227 | *n = 8192; | 1287 | core.cts = cts; |
| 1228 | else | 1288 | if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { |
| 1229 | *n = 4096; | 1289 | core.aud_par_busclk = 0; |
| 1290 | core.cts_mode = HDMI_AUDIO_CTS_MODE_SW; | ||
| 1291 | core.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK); | ||
| 1292 | } else { | ||
| 1293 | core.aud_par_busclk = (((128 * 31) - 1) << 8); | ||
| 1294 | core.cts_mode = HDMI_AUDIO_CTS_MODE_HW; | ||
| 1295 | core.use_mclk = true; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | if (core.use_mclk) | ||
| 1299 | core.mclk_mode = HDMI_AUDIO_MCLK_128FS; | ||
| 1300 | |||
| 1301 | /* Audio channels settings */ | ||
| 1302 | channel_count = (audio->cea->db1_ct_cc & | ||
| 1303 | CEA861_AUDIO_INFOFRAME_DB1CC) + 1; | ||
| 1304 | |||
| 1305 | switch (channel_count) { | ||
| 1306 | case 2: | ||
| 1307 | audio_format.active_chnnls_msk = 0x03; | ||
| 1308 | break; | ||
| 1309 | case 3: | ||
| 1310 | audio_format.active_chnnls_msk = 0x07; | ||
| 1311 | break; | ||
| 1312 | case 4: | ||
| 1313 | audio_format.active_chnnls_msk = 0x0f; | ||
| 1314 | break; | ||
| 1315 | case 5: | ||
| 1316 | audio_format.active_chnnls_msk = 0x1f; | ||
| 1230 | break; | 1317 | break; |
| 1231 | case 44100: | 1318 | case 6: |
| 1232 | *n = 6272; | 1319 | audio_format.active_chnnls_msk = 0x3f; |
| 1233 | break; | 1320 | break; |
| 1234 | case 48000: | 1321 | case 7: |
| 1235 | if ((deep_color == 125) && ((pclk == 54054) | 1322 | audio_format.active_chnnls_msk = 0x7f; |
| 1236 | || (pclk == 74250))) | 1323 | break; |
| 1237 | *n = 8192; | 1324 | case 8: |
| 1238 | else | 1325 | audio_format.active_chnnls_msk = 0xff; |
| 1239 | *n = 6144; | ||
| 1240 | break; | 1326 | break; |
| 1241 | default: | 1327 | default: |
| 1242 | *n = 0; | ||
| 1243 | return -EINVAL; | 1328 | return -EINVAL; |
| 1244 | } | 1329 | } |
| 1245 | 1330 | ||
| 1246 | /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ | 1331 | /* |
| 1247 | *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); | 1332 | * the HDMI IP needs to enable four stereo channels when transmitting |
| 1333 | * more than 2 audio channels | ||
| 1334 | */ | ||
| 1335 | if (channel_count == 2) { | ||
| 1336 | audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; | ||
| 1337 | core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN; | ||
| 1338 | core.layout = HDMI_AUDIO_LAYOUT_2CH; | ||
| 1339 | } else { | ||
| 1340 | audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS; | ||
| 1341 | core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN | | ||
| 1342 | HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN | | ||
| 1343 | HDMI_AUDIO_I2S_SD3_EN; | ||
| 1344 | core.layout = HDMI_AUDIO_LAYOUT_8CH; | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | core.en_spdif = false; | ||
| 1348 | /* use sample frequency from channel status word */ | ||
| 1349 | core.fs_override = true; | ||
| 1350 | /* enable ACR packets */ | ||
| 1351 | core.en_acr_pkt = true; | ||
| 1352 | /* disable direct streaming digital audio */ | ||
| 1353 | core.en_dsd_audio = false; | ||
| 1354 | /* use parallel audio interface */ | ||
| 1355 | core.en_parallel_aud_input = true; | ||
| 1356 | |||
| 1357 | /* DMA settings */ | ||
| 1358 | if (word_length_16b) | ||
| 1359 | audio_dma.transfer_size = 0x10; | ||
| 1360 | else | ||
| 1361 | audio_dma.transfer_size = 0x20; | ||
| 1362 | audio_dma.block_size = 0xC0; | ||
| 1363 | audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; | ||
| 1364 | audio_dma.fifo_threshold = 0x20; /* in number of samples */ | ||
| 1365 | |||
| 1366 | /* audio FIFO format settings */ | ||
| 1367 | if (word_length_16b) { | ||
| 1368 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES; | ||
| 1369 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS; | ||
| 1370 | audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT; | ||
| 1371 | } else { | ||
| 1372 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE; | ||
| 1373 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS; | ||
| 1374 | audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT; | ||
| 1375 | } | ||
| 1376 | audio_format.type = HDMI_AUDIO_TYPE_LPCM; | ||
| 1377 | audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST; | ||
| 1378 | /* disable start/stop signals of IEC 60958 blocks */ | ||
| 1379 | audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON; | ||
| 1380 | |||
| 1381 | /* configure DMA and audio FIFO format*/ | ||
| 1382 | ti_hdmi_4xxx_wp_audio_config_dma(ip_data, &audio_dma); | ||
| 1383 | ti_hdmi_4xxx_wp_audio_config_format(ip_data, &audio_format); | ||
| 1384 | |||
| 1385 | /* configure the core*/ | ||
| 1386 | ti_hdmi_4xxx_core_audio_config(ip_data, &core); | ||
| 1387 | |||
| 1388 | /* configure CEA 861 audio infoframe*/ | ||
| 1389 | ti_hdmi_4xxx_core_audio_infoframe_cfg(ip_data, audio->cea); | ||
| 1248 | 1390 | ||
| 1249 | return 0; | 1391 | return 0; |
| 1250 | } | 1392 | } |
| 1251 | 1393 | ||
| 1252 | void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable) | 1394 | int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data) |
| 1395 | { | ||
| 1396 | REG_FLD_MOD(hdmi_wp_base(ip_data), | ||
| 1397 | HDMI_WP_AUDIO_CTRL, true, 31, 31); | ||
| 1398 | return 0; | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data) | ||
| 1402 | { | ||
| 1403 | REG_FLD_MOD(hdmi_wp_base(ip_data), | ||
| 1404 | HDMI_WP_AUDIO_CTRL, false, 31, 31); | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data) | ||
| 1253 | { | 1408 | { |
| 1254 | REG_FLD_MOD(hdmi_av_base(ip_data), | 1409 | REG_FLD_MOD(hdmi_av_base(ip_data), |
| 1255 | HDMI_CORE_AV_AUD_MODE, enable, 0, 0); | 1410 | HDMI_CORE_AV_AUD_MODE, true, 0, 0); |
| 1256 | REG_FLD_MOD(hdmi_wp_base(ip_data), | 1411 | REG_FLD_MOD(hdmi_wp_base(ip_data), |
| 1257 | HDMI_WP_AUDIO_CTRL, enable, 31, 31); | 1412 | HDMI_WP_AUDIO_CTRL, true, 30, 30); |
| 1413 | return 0; | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data) | ||
| 1417 | { | ||
| 1418 | REG_FLD_MOD(hdmi_av_base(ip_data), | ||
| 1419 | HDMI_CORE_AV_AUD_MODE, false, 0, 0); | ||
| 1258 | REG_FLD_MOD(hdmi_wp_base(ip_data), | 1420 | REG_FLD_MOD(hdmi_wp_base(ip_data), |
| 1259 | HDMI_WP_AUDIO_CTRL, enable, 30, 30); | 1421 | HDMI_WP_AUDIO_CTRL, false, 30, 30); |
| 1260 | } | 1422 | } |
| 1261 | #endif | 1423 | #endif |
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h index a14d1a0e6e41..8366ae19e82e 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h | |||
| @@ -24,11 +24,6 @@ | |||
| 24 | #include <linux/string.h> | 24 | #include <linux/string.h> |
| 25 | #include <video/omapdss.h> | 25 | #include <video/omapdss.h> |
| 26 | #include "ti_hdmi.h" | 26 | #include "ti_hdmi.h" |
| 27 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
| 28 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
| 29 | #include <sound/soc.h> | ||
| 30 | #include <sound/pcm_params.h> | ||
| 31 | #endif | ||
| 32 | 27 | ||
| 33 | /* HDMI Wrapper */ | 28 | /* HDMI Wrapper */ |
| 34 | 29 | ||
| @@ -57,6 +52,13 @@ | |||
| 57 | #define HDMI_CORE_SYS_SRST 0x14 | 52 | #define HDMI_CORE_SYS_SRST 0x14 |
| 58 | #define HDMI_CORE_CTRL1 0x20 | 53 | #define HDMI_CORE_CTRL1 0x20 |
| 59 | #define HDMI_CORE_SYS_SYS_STAT 0x24 | 54 | #define HDMI_CORE_SYS_SYS_STAT 0x24 |
| 55 | #define HDMI_CORE_SYS_DE_DLY 0xC8 | ||
| 56 | #define HDMI_CORE_SYS_DE_CTRL 0xCC | ||
| 57 | #define HDMI_CORE_SYS_DE_TOP 0xD0 | ||
| 58 | #define HDMI_CORE_SYS_DE_CNTL 0xD8 | ||
| 59 | #define HDMI_CORE_SYS_DE_CNTH 0xDC | ||
| 60 | #define HDMI_CORE_SYS_DE_LINL 0xE0 | ||
| 61 | #define HDMI_CORE_SYS_DE_LINH_1 0xE4 | ||
| 60 | #define HDMI_CORE_SYS_VID_ACEN 0x124 | 62 | #define HDMI_CORE_SYS_VID_ACEN 0x124 |
| 61 | #define HDMI_CORE_SYS_VID_MODE 0x128 | 63 | #define HDMI_CORE_SYS_VID_MODE 0x128 |
| 62 | #define HDMI_CORE_SYS_INTR_STATE 0x1C0 | 64 | #define HDMI_CORE_SYS_INTR_STATE 0x1C0 |
| @@ -66,50 +68,24 @@ | |||
| 66 | #define HDMI_CORE_SYS_INTR4 0x1D0 | 68 | #define HDMI_CORE_SYS_INTR4 0x1D0 |
| 67 | #define HDMI_CORE_SYS_UMASK1 0x1D4 | 69 | #define HDMI_CORE_SYS_UMASK1 0x1D4 |
| 68 | #define HDMI_CORE_SYS_TMDS_CTRL 0x208 | 70 | #define HDMI_CORE_SYS_TMDS_CTRL 0x208 |
| 69 | #define HDMI_CORE_SYS_DE_DLY 0xC8 | 71 | |
| 70 | #define HDMI_CORE_SYS_DE_CTRL 0xCC | ||
| 71 | #define HDMI_CORE_SYS_DE_TOP 0xD0 | ||
| 72 | #define HDMI_CORE_SYS_DE_CNTL 0xD8 | ||
| 73 | #define HDMI_CORE_SYS_DE_CNTH 0xDC | ||
| 74 | #define HDMI_CORE_SYS_DE_LINL 0xE0 | ||
| 75 | #define HDMI_CORE_SYS_DE_LINH_1 0xE4 | ||
| 76 | #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 | 72 | #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 |
| 77 | #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 | 73 | #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 |
| 78 | #define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 | 74 | #define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 |
| 79 | #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 | 75 | #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 |
| 80 | 76 | ||
| 81 | /* HDMI DDC E-DID */ | 77 | /* HDMI DDC E-DID */ |
| 82 | #define HDMI_CORE_DDC_CMD 0x3CC | ||
| 83 | #define HDMI_CORE_DDC_STATUS 0x3C8 | ||
| 84 | #define HDMI_CORE_DDC_ADDR 0x3B4 | 78 | #define HDMI_CORE_DDC_ADDR 0x3B4 |
| 79 | #define HDMI_CORE_DDC_SEGM 0x3B8 | ||
| 85 | #define HDMI_CORE_DDC_OFFSET 0x3BC | 80 | #define HDMI_CORE_DDC_OFFSET 0x3BC |
| 86 | #define HDMI_CORE_DDC_COUNT1 0x3C0 | 81 | #define HDMI_CORE_DDC_COUNT1 0x3C0 |
| 87 | #define HDMI_CORE_DDC_COUNT2 0x3C4 | 82 | #define HDMI_CORE_DDC_COUNT2 0x3C4 |
| 83 | #define HDMI_CORE_DDC_STATUS 0x3C8 | ||
| 84 | #define HDMI_CORE_DDC_CMD 0x3CC | ||
| 88 | #define HDMI_CORE_DDC_DATA 0x3D0 | 85 | #define HDMI_CORE_DDC_DATA 0x3D0 |
| 89 | #define HDMI_CORE_DDC_SEGM 0x3B8 | ||
| 90 | 86 | ||
| 91 | /* HDMI IP Core Audio Video */ | 87 | /* HDMI IP Core Audio Video */ |
| 92 | 88 | ||
| 93 | #define HDMI_CORE_AV_HDMI_CTRL 0xBC | ||
| 94 | #define HDMI_CORE_AV_DPD 0xF4 | ||
| 95 | #define HDMI_CORE_AV_PB_CTRL1 0xF8 | ||
| 96 | #define HDMI_CORE_AV_PB_CTRL2 0xFC | ||
| 97 | #define HDMI_CORE_AV_AVI_TYPE 0x100 | ||
| 98 | #define HDMI_CORE_AV_AVI_VERS 0x104 | ||
| 99 | #define HDMI_CORE_AV_AVI_LEN 0x108 | ||
| 100 | #define HDMI_CORE_AV_AVI_CHSUM 0x10C | ||
| 101 | #define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110) | ||
| 102 | #define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15 | ||
| 103 | #define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190) | ||
| 104 | #define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27 | ||
| 105 | #define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210) | ||
| 106 | #define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10 | ||
| 107 | #define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290) | ||
| 108 | #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27 | ||
| 109 | #define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300) | ||
| 110 | #define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31 | ||
| 111 | #define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380) | ||
| 112 | #define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31 | ||
| 113 | #define HDMI_CORE_AV_ACR_CTRL 0x4 | 89 | #define HDMI_CORE_AV_ACR_CTRL 0x4 |
| 114 | #define HDMI_CORE_AV_FREQ_SVAL 0x8 | 90 | #define HDMI_CORE_AV_FREQ_SVAL 0x8 |
| 115 | #define HDMI_CORE_AV_N_SVAL1 0xC | 91 | #define HDMI_CORE_AV_N_SVAL1 0xC |
| @@ -148,25 +124,39 @@ | |||
| 148 | #define HDMI_CORE_AV_AVI_VERS 0x104 | 124 | #define HDMI_CORE_AV_AVI_VERS 0x104 |
| 149 | #define HDMI_CORE_AV_AVI_LEN 0x108 | 125 | #define HDMI_CORE_AV_AVI_LEN 0x108 |
| 150 | #define HDMI_CORE_AV_AVI_CHSUM 0x10C | 126 | #define HDMI_CORE_AV_AVI_CHSUM 0x10C |
| 127 | #define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110) | ||
| 151 | #define HDMI_CORE_AV_SPD_TYPE 0x180 | 128 | #define HDMI_CORE_AV_SPD_TYPE 0x180 |
| 152 | #define HDMI_CORE_AV_SPD_VERS 0x184 | 129 | #define HDMI_CORE_AV_SPD_VERS 0x184 |
| 153 | #define HDMI_CORE_AV_SPD_LEN 0x188 | 130 | #define HDMI_CORE_AV_SPD_LEN 0x188 |
| 154 | #define HDMI_CORE_AV_SPD_CHSUM 0x18C | 131 | #define HDMI_CORE_AV_SPD_CHSUM 0x18C |
| 132 | #define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190) | ||
| 155 | #define HDMI_CORE_AV_AUDIO_TYPE 0x200 | 133 | #define HDMI_CORE_AV_AUDIO_TYPE 0x200 |
| 156 | #define HDMI_CORE_AV_AUDIO_VERS 0x204 | 134 | #define HDMI_CORE_AV_AUDIO_VERS 0x204 |
| 157 | #define HDMI_CORE_AV_AUDIO_LEN 0x208 | 135 | #define HDMI_CORE_AV_AUDIO_LEN 0x208 |
| 158 | #define HDMI_CORE_AV_AUDIO_CHSUM 0x20C | 136 | #define HDMI_CORE_AV_AUDIO_CHSUM 0x20C |
| 137 | #define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210) | ||
| 159 | #define HDMI_CORE_AV_MPEG_TYPE 0x280 | 138 | #define HDMI_CORE_AV_MPEG_TYPE 0x280 |
| 160 | #define HDMI_CORE_AV_MPEG_VERS 0x284 | 139 | #define HDMI_CORE_AV_MPEG_VERS 0x284 |
| 161 | #define HDMI_CORE_AV_MPEG_LEN 0x288 | 140 | #define HDMI_CORE_AV_MPEG_LEN 0x288 |
| 162 | #define HDMI_CORE_AV_MPEG_CHSUM 0x28C | 141 | #define HDMI_CORE_AV_MPEG_CHSUM 0x28C |
| 142 | #define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290) | ||
| 143 | #define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300) | ||
| 163 | #define HDMI_CORE_AV_CP_BYTE1 0x37C | 144 | #define HDMI_CORE_AV_CP_BYTE1 0x37C |
| 145 | #define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380) | ||
| 164 | #define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC | 146 | #define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC |
| 147 | |||
| 165 | #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 | 148 | #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 |
| 166 | #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 | 149 | #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 |
| 167 | #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 | 150 | #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 |
| 168 | #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 | 151 | #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 |
| 169 | 152 | ||
| 153 | #define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15 | ||
| 154 | #define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27 | ||
| 155 | #define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10 | ||
| 156 | #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27 | ||
| 157 | #define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31 | ||
| 158 | #define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31 | ||
| 159 | |||
| 170 | /* PLL */ | 160 | /* PLL */ |
| 171 | 161 | ||
| 172 | #define PLLCTRL_PLL_CONTROL 0x0 | 162 | #define PLLCTRL_PLL_CONTROL 0x0 |
| @@ -284,35 +274,6 @@ enum hdmi_core_infoframe { | |||
| 284 | HDMI_INFOFRAME_AVI_DB5PR_8 = 7, | 274 | HDMI_INFOFRAME_AVI_DB5PR_8 = 7, |
| 285 | HDMI_INFOFRAME_AVI_DB5PR_9 = 8, | 275 | HDMI_INFOFRAME_AVI_DB5PR_9 = 8, |
| 286 | HDMI_INFOFRAME_AVI_DB5PR_10 = 9, | 276 | HDMI_INFOFRAME_AVI_DB5PR_10 = 9, |
| 287 | HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM = 0, | ||
| 288 | HDMI_INFOFRAME_AUDIO_DB1CT_IEC60958 = 1, | ||
| 289 | HDMI_INFOFRAME_AUDIO_DB1CT_AC3 = 2, | ||
| 290 | HDMI_INFOFRAME_AUDIO_DB1CT_MPEG1 = 3, | ||
| 291 | HDMI_INFOFRAME_AUDIO_DB1CT_MP3 = 4, | ||
| 292 | HDMI_INFOFRAME_AUDIO_DB1CT_MPEG2_MULTICH = 5, | ||
| 293 | HDMI_INFOFRAME_AUDIO_DB1CT_AAC = 6, | ||
| 294 | HDMI_INFOFRAME_AUDIO_DB1CT_DTS = 7, | ||
| 295 | HDMI_INFOFRAME_AUDIO_DB1CT_ATRAC = 8, | ||
| 296 | HDMI_INFOFRAME_AUDIO_DB1CT_ONEBIT = 9, | ||
| 297 | HDMI_INFOFRAME_AUDIO_DB1CT_DOLBY_DIGITAL_PLUS = 10, | ||
| 298 | HDMI_INFOFRAME_AUDIO_DB1CT_DTS_HD = 11, | ||
| 299 | HDMI_INFOFRAME_AUDIO_DB1CT_MAT = 12, | ||
| 300 | HDMI_INFOFRAME_AUDIO_DB1CT_DST = 13, | ||
| 301 | HDMI_INFOFRAME_AUDIO_DB1CT_WMA_PRO = 14, | ||
| 302 | HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM = 0, | ||
| 303 | HDMI_INFOFRAME_AUDIO_DB2SF_32000 = 1, | ||
| 304 | HDMI_INFOFRAME_AUDIO_DB2SF_44100 = 2, | ||
| 305 | HDMI_INFOFRAME_AUDIO_DB2SF_48000 = 3, | ||
| 306 | HDMI_INFOFRAME_AUDIO_DB2SF_88200 = 4, | ||
| 307 | HDMI_INFOFRAME_AUDIO_DB2SF_96000 = 5, | ||
| 308 | HDMI_INFOFRAME_AUDIO_DB2SF_176400 = 6, | ||
| 309 | HDMI_INFOFRAME_AUDIO_DB2SF_192000 = 7, | ||
| 310 | HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM = 0, | ||
| 311 | HDMI_INFOFRAME_AUDIO_DB2SS_16BIT = 1, | ||
| 312 | HDMI_INFOFRAME_AUDIO_DB2SS_20BIT = 2, | ||
| 313 | HDMI_INFOFRAME_AUDIO_DB2SS_24BIT = 3, | ||
| 314 | HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PERMITTED = 0, | ||
| 315 | HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PROHIBITED = 1 | ||
| 316 | }; | 277 | }; |
| 317 | 278 | ||
| 318 | enum hdmi_packing_mode { | 279 | enum hdmi_packing_mode { |
| @@ -322,17 +283,6 @@ enum hdmi_packing_mode { | |||
| 322 | HDMI_PACK_ALREADYPACKED = 7 | 283 | HDMI_PACK_ALREADYPACKED = 7 |
| 323 | }; | 284 | }; |
| 324 | 285 | ||
| 325 | enum hdmi_core_audio_sample_freq { | ||
| 326 | HDMI_AUDIO_FS_32000 = 0x3, | ||
| 327 | HDMI_AUDIO_FS_44100 = 0x0, | ||
| 328 | HDMI_AUDIO_FS_48000 = 0x2, | ||
| 329 | HDMI_AUDIO_FS_88200 = 0x8, | ||
| 330 | HDMI_AUDIO_FS_96000 = 0xA, | ||
| 331 | HDMI_AUDIO_FS_176400 = 0xC, | ||
| 332 | HDMI_AUDIO_FS_192000 = 0xE, | ||
| 333 | HDMI_AUDIO_FS_NOT_INDICATED = 0x1 | ||
| 334 | }; | ||
| 335 | |||
| 336 | enum hdmi_core_audio_layout { | 286 | enum hdmi_core_audio_layout { |
| 337 | HDMI_AUDIO_LAYOUT_2CH = 0, | 287 | HDMI_AUDIO_LAYOUT_2CH = 0, |
| 338 | HDMI_AUDIO_LAYOUT_8CH = 1 | 288 | HDMI_AUDIO_LAYOUT_8CH = 1 |
| @@ -387,37 +337,12 @@ enum hdmi_audio_blk_strt_end_sig { | |||
| 387 | }; | 337 | }; |
| 388 | 338 | ||
| 389 | enum hdmi_audio_i2s_config { | 339 | enum hdmi_audio_i2s_config { |
| 390 | HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT = 0, | ||
| 391 | HDMI_AUDIO_I2S_WS_POLARIT_YLOW_IS_RIGHT = 1, | ||
| 392 | HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0, | 340 | HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0, |
| 393 | HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1, | 341 | HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1, |
| 394 | HDMI_AUDIO_I2S_MAX_WORD_20BITS = 0, | ||
| 395 | HDMI_AUDIO_I2S_MAX_WORD_24BITS = 1, | ||
| 396 | HDMI_AUDIO_I2S_CHST_WORD_NOT_SPECIFIED = 0, | ||
| 397 | HDMI_AUDIO_I2S_CHST_WORD_16_BITS = 1, | ||
| 398 | HDMI_AUDIO_I2S_CHST_WORD_17_BITS = 6, | ||
| 399 | HDMI_AUDIO_I2S_CHST_WORD_18_BITS = 2, | ||
| 400 | HDMI_AUDIO_I2S_CHST_WORD_19_BITS = 4, | ||
| 401 | HDMI_AUDIO_I2S_CHST_WORD_20_BITS_20MAX = 5, | ||
| 402 | HDMI_AUDIO_I2S_CHST_WORD_20_BITS_24MAX = 1, | ||
| 403 | HDMI_AUDIO_I2S_CHST_WORD_21_BITS = 6, | ||
| 404 | HDMI_AUDIO_I2S_CHST_WORD_22_BITS = 2, | ||
| 405 | HDMI_AUDIO_I2S_CHST_WORD_23_BITS = 4, | ||
| 406 | HDMI_AUDIO_I2S_CHST_WORD_24_BITS = 5, | ||
| 407 | HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0, | 342 | HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0, |
| 408 | HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1, | 343 | HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1, |
| 409 | HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0, | 344 | HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0, |
| 410 | HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1, | 345 | HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1, |
| 411 | HDMI_AUDIO_I2S_INPUT_LENGTH_NA = 0, | ||
| 412 | HDMI_AUDIO_I2S_INPUT_LENGTH_16 = 2, | ||
| 413 | HDMI_AUDIO_I2S_INPUT_LENGTH_17 = 12, | ||
| 414 | HDMI_AUDIO_I2S_INPUT_LENGTH_18 = 4, | ||
| 415 | HDMI_AUDIO_I2S_INPUT_LENGTH_19 = 8, | ||
| 416 | HDMI_AUDIO_I2S_INPUT_LENGTH_20 = 10, | ||
| 417 | HDMI_AUDIO_I2S_INPUT_LENGTH_21 = 13, | ||
| 418 | HDMI_AUDIO_I2S_INPUT_LENGTH_22 = 5, | ||
| 419 | HDMI_AUDIO_I2S_INPUT_LENGTH_23 = 9, | ||
| 420 | HDMI_AUDIO_I2S_INPUT_LENGTH_24 = 11, | ||
| 421 | HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0, | 346 | HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0, |
| 422 | HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1, | 347 | HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1, |
| 423 | HDMI_AUDIO_I2S_SD0_EN = 1, | 348 | HDMI_AUDIO_I2S_SD0_EN = 1, |
| @@ -446,20 +371,6 @@ struct hdmi_core_video_config { | |||
| 446 | enum hdmi_core_tclkselclkmult tclk_sel_clkmult; | 371 | enum hdmi_core_tclkselclkmult tclk_sel_clkmult; |
| 447 | }; | 372 | }; |
| 448 | 373 | ||
| 449 | /* | ||
| 450 | * Refer to section 8.2 in HDMI 1.3 specification for | ||
| 451 | * details about infoframe databytes | ||
| 452 | */ | ||
| 453 | struct hdmi_core_infoframe_audio { | ||
| 454 | u8 db1_coding_type; | ||
| 455 | u8 db1_channel_count; | ||
| 456 | u8 db2_sample_freq; | ||
| 457 | u8 db2_sample_size; | ||
| 458 | u8 db4_channel_alloc; | ||
| 459 | bool db5_downmix_inh; | ||
| 460 | u8 db5_lsv; /* Level shift values for downmix */ | ||
| 461 | }; | ||
| 462 | |||
| 463 | struct hdmi_core_packet_enable_repeat { | 374 | struct hdmi_core_packet_enable_repeat { |
| 464 | u32 audio_pkt; | 375 | u32 audio_pkt; |
| 465 | u32 audio_pkt_repeat; | 376 | u32 audio_pkt_repeat; |
| @@ -496,15 +407,10 @@ struct hdmi_audio_dma { | |||
| 496 | }; | 407 | }; |
| 497 | 408 | ||
| 498 | struct hdmi_core_audio_i2s_config { | 409 | struct hdmi_core_audio_i2s_config { |
| 499 | u8 word_max_length; | ||
| 500 | u8 word_length; | ||
| 501 | u8 in_length_bits; | 410 | u8 in_length_bits; |
| 502 | u8 justification; | 411 | u8 justification; |
| 503 | u8 en_high_bitrate_aud; | ||
| 504 | u8 sck_edge_mode; | 412 | u8 sck_edge_mode; |
| 505 | u8 cbit_order; | ||
| 506 | u8 vbit; | 413 | u8 vbit; |
| 507 | u8 ws_polarity; | ||
| 508 | u8 direction; | 414 | u8 direction; |
| 509 | u8 shift; | 415 | u8 shift; |
| 510 | u8 active_sds; | 416 | u8 active_sds; |
| @@ -512,7 +418,7 @@ struct hdmi_core_audio_i2s_config { | |||
| 512 | 418 | ||
| 513 | struct hdmi_core_audio_config { | 419 | struct hdmi_core_audio_config { |
| 514 | struct hdmi_core_audio_i2s_config i2s_cfg; | 420 | struct hdmi_core_audio_i2s_config i2s_cfg; |
| 515 | enum hdmi_core_audio_sample_freq freq_sample; | 421 | struct snd_aes_iec958 *iec60958_cfg; |
| 516 | bool fs_override; | 422 | bool fs_override; |
| 517 | u32 n; | 423 | u32 n; |
| 518 | u32 cts; | 424 | u32 cts; |
| @@ -527,17 +433,4 @@ struct hdmi_core_audio_config { | |||
| 527 | bool en_spdif; | 433 | bool en_spdif; |
| 528 | }; | 434 | }; |
| 529 | 435 | ||
| 530 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
| 531 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
| 532 | int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, | ||
| 533 | u32 sample_freq, u32 *n, u32 *cts); | ||
| 534 | void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, | ||
| 535 | struct hdmi_core_infoframe_audio *info_aud); | ||
| 536 | void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, | ||
| 537 | struct hdmi_core_audio_config *cfg); | ||
| 538 | void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data, | ||
| 539 | struct hdmi_audio_dma *aud_dma); | ||
| 540 | void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data, | ||
| 541 | struct hdmi_audio_format *aud_fmt); | ||
| 542 | #endif | ||
| 543 | #endif | 436 | #endif |
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 9c3daf71750c..2b8973931ff4 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c | |||
| @@ -415,6 +415,7 @@ static const struct venc_config *venc_timings_to_config( | |||
| 415 | return &venc_config_ntsc_trm; | 415 | return &venc_config_ntsc_trm; |
| 416 | 416 | ||
| 417 | BUG(); | 417 | BUG(); |
| 418 | return NULL; | ||
| 418 | } | 419 | } |
| 419 | 420 | ||
| 420 | static int venc_power_on(struct omap_dss_device *dssdev) | 421 | static int venc_power_on(struct omap_dss_device *dssdev) |
| @@ -440,10 +441,11 @@ static int venc_power_on(struct omap_dss_device *dssdev) | |||
| 440 | 441 | ||
| 441 | venc_write_reg(VENC_OUTPUT_CONTROL, l); | 442 | venc_write_reg(VENC_OUTPUT_CONTROL, l); |
| 442 | 443 | ||
| 443 | dispc_set_digit_size(dssdev->panel.timings.x_res, | 444 | dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); |
| 444 | dssdev->panel.timings.y_res/2); | ||
| 445 | 445 | ||
| 446 | regulator_enable(venc.vdda_dac_reg); | 446 | r = regulator_enable(venc.vdda_dac_reg); |
| 447 | if (r) | ||
| 448 | goto err; | ||
| 447 | 449 | ||
| 448 | if (dssdev->platform_enable) | 450 | if (dssdev->platform_enable) |
| 449 | dssdev->platform_enable(dssdev); | 451 | dssdev->platform_enable(dssdev); |
| @@ -485,16 +487,68 @@ unsigned long venc_get_pixel_clock(void) | |||
| 485 | return 13500000; | 487 | return 13500000; |
| 486 | } | 488 | } |
| 487 | 489 | ||
| 490 | static ssize_t display_output_type_show(struct device *dev, | ||
| 491 | struct device_attribute *attr, char *buf) | ||
| 492 | { | ||
| 493 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
| 494 | const char *ret; | ||
| 495 | |||
| 496 | switch (dssdev->phy.venc.type) { | ||
| 497 | case OMAP_DSS_VENC_TYPE_COMPOSITE: | ||
| 498 | ret = "composite"; | ||
| 499 | break; | ||
| 500 | case OMAP_DSS_VENC_TYPE_SVIDEO: | ||
| 501 | ret = "svideo"; | ||
| 502 | break; | ||
| 503 | default: | ||
| 504 | return -EINVAL; | ||
| 505 | } | ||
| 506 | |||
| 507 | return snprintf(buf, PAGE_SIZE, "%s\n", ret); | ||
| 508 | } | ||
| 509 | |||
| 510 | static ssize_t display_output_type_store(struct device *dev, | ||
| 511 | struct device_attribute *attr, const char *buf, size_t size) | ||
| 512 | { | ||
| 513 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
| 514 | enum omap_dss_venc_type new_type; | ||
| 515 | |||
| 516 | if (sysfs_streq("composite", buf)) | ||
| 517 | new_type = OMAP_DSS_VENC_TYPE_COMPOSITE; | ||
| 518 | else if (sysfs_streq("svideo", buf)) | ||
| 519 | new_type = OMAP_DSS_VENC_TYPE_SVIDEO; | ||
| 520 | else | ||
| 521 | return -EINVAL; | ||
| 522 | |||
| 523 | mutex_lock(&venc.venc_lock); | ||
| 524 | |||
| 525 | if (dssdev->phy.venc.type != new_type) { | ||
| 526 | dssdev->phy.venc.type = new_type; | ||
| 527 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | ||
| 528 | venc_power_off(dssdev); | ||
| 529 | venc_power_on(dssdev); | ||
| 530 | } | ||
| 531 | } | ||
| 532 | |||
| 533 | mutex_unlock(&venc.venc_lock); | ||
| 534 | |||
| 535 | return size; | ||
| 536 | } | ||
| 537 | |||
| 538 | static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR, | ||
| 539 | display_output_type_show, display_output_type_store); | ||
| 540 | |||
| 488 | /* driver */ | 541 | /* driver */ |
| 489 | static int venc_panel_probe(struct omap_dss_device *dssdev) | 542 | static int venc_panel_probe(struct omap_dss_device *dssdev) |
| 490 | { | 543 | { |
| 491 | dssdev->panel.timings = omap_dss_pal_timings; | 544 | dssdev->panel.timings = omap_dss_pal_timings; |
| 492 | 545 | ||
| 493 | return 0; | 546 | return device_create_file(&dssdev->dev, &dev_attr_output_type); |
| 494 | } | 547 | } |
| 495 | 548 | ||
| 496 | static void venc_panel_remove(struct omap_dss_device *dssdev) | 549 | static void venc_panel_remove(struct omap_dss_device *dssdev) |
| 497 | { | 550 | { |
| 551 | device_remove_file(&dssdev->dev, &dev_attr_output_type); | ||
| 498 | } | 552 | } |
| 499 | 553 | ||
| 500 | static int venc_panel_enable(struct omap_dss_device *dssdev) | 554 | static int venc_panel_enable(struct omap_dss_device *dssdev) |
| @@ -577,12 +631,6 @@ static int venc_panel_resume(struct omap_dss_device *dssdev) | |||
| 577 | return venc_panel_enable(dssdev); | 631 | return venc_panel_enable(dssdev); |
| 578 | } | 632 | } |
| 579 | 633 | ||
| 580 | static void venc_get_timings(struct omap_dss_device *dssdev, | ||
| 581 | struct omap_video_timings *timings) | ||
| 582 | { | ||
| 583 | *timings = dssdev->panel.timings; | ||
| 584 | } | ||
| 585 | |||
| 586 | static void venc_set_timings(struct omap_dss_device *dssdev, | 634 | static void venc_set_timings(struct omap_dss_device *dssdev, |
| 587 | struct omap_video_timings *timings) | 635 | struct omap_video_timings *timings) |
| 588 | { | 636 | { |
| @@ -597,6 +645,8 @@ static void venc_set_timings(struct omap_dss_device *dssdev, | |||
| 597 | /* turn the venc off and on to get new timings to use */ | 645 | /* turn the venc off and on to get new timings to use */ |
| 598 | venc_panel_disable(dssdev); | 646 | venc_panel_disable(dssdev); |
| 599 | venc_panel_enable(dssdev); | 647 | venc_panel_enable(dssdev); |
| 648 | } else { | ||
| 649 | dss_mgr_set_timings(dssdev->manager, timings); | ||
| 600 | } | 650 | } |
| 601 | } | 651 | } |
| 602 | 652 | ||
| @@ -661,7 +711,6 @@ static struct omap_dss_driver venc_driver = { | |||
| 661 | .get_resolution = omapdss_default_get_resolution, | 711 | .get_resolution = omapdss_default_get_resolution, |
| 662 | .get_recommended_bpp = omapdss_default_get_recommended_bpp, | 712 | .get_recommended_bpp = omapdss_default_get_recommended_bpp, |
| 663 | 713 | ||
| 664 | .get_timings = venc_get_timings, | ||
| 665 | .set_timings = venc_set_timings, | 714 | .set_timings = venc_set_timings, |
| 666 | .check_timings = venc_check_timings, | 715 | .check_timings = venc_check_timings, |
| 667 | 716 | ||
| @@ -675,7 +724,7 @@ static struct omap_dss_driver venc_driver = { | |||
| 675 | }; | 724 | }; |
| 676 | /* driver end */ | 725 | /* driver end */ |
| 677 | 726 | ||
| 678 | int venc_init_display(struct omap_dss_device *dssdev) | 727 | static int __init venc_init_display(struct omap_dss_device *dssdev) |
| 679 | { | 728 | { |
| 680 | DSSDBG("init_display\n"); | 729 | DSSDBG("init_display\n"); |
| 681 | 730 | ||
| @@ -695,7 +744,7 @@ int venc_init_display(struct omap_dss_device *dssdev) | |||
| 695 | return 0; | 744 | return 0; |
| 696 | } | 745 | } |
| 697 | 746 | ||
| 698 | void venc_dump_regs(struct seq_file *s) | 747 | static void venc_dump_regs(struct seq_file *s) |
| 699 | { | 748 | { |
| 700 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) | 749 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) |
| 701 | 750 | ||
| @@ -779,8 +828,32 @@ static void venc_put_clocks(void) | |||
| 779 | clk_put(venc.tv_dac_clk); | 828 | clk_put(venc.tv_dac_clk); |
| 780 | } | 829 | } |
| 781 | 830 | ||
| 831 | static void __init venc_probe_pdata(struct platform_device *pdev) | ||
| 832 | { | ||
| 833 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | ||
| 834 | int r, i; | ||
| 835 | |||
| 836 | for (i = 0; i < pdata->num_devices; ++i) { | ||
| 837 | struct omap_dss_device *dssdev = pdata->devices[i]; | ||
| 838 | |||
| 839 | if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) | ||
| 840 | continue; | ||
| 841 | |||
| 842 | r = venc_init_display(dssdev); | ||
| 843 | if (r) { | ||
| 844 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | ||
| 845 | continue; | ||
| 846 | } | ||
| 847 | |||
| 848 | r = omap_dss_register_device(dssdev, &pdev->dev, i); | ||
| 849 | if (r) | ||
| 850 | DSSERR("device %s register failed: %d\n", | ||
| 851 | dssdev->name, r); | ||
| 852 | } | ||
| 853 | } | ||
| 854 | |||
| 782 | /* VENC HW IP initialisation */ | 855 | /* VENC HW IP initialisation */ |
| 783 | static int omap_venchw_probe(struct platform_device *pdev) | 856 | static int __init omap_venchw_probe(struct platform_device *pdev) |
| 784 | { | 857 | { |
| 785 | u8 rev_id; | 858 | u8 rev_id; |
| 786 | struct resource *venc_mem; | 859 | struct resource *venc_mem; |
| @@ -824,6 +897,10 @@ static int omap_venchw_probe(struct platform_device *pdev) | |||
| 824 | if (r) | 897 | if (r) |
| 825 | goto err_reg_panel_driver; | 898 | goto err_reg_panel_driver; |
| 826 | 899 | ||
| 900 | dss_debugfs_create_file("venc", venc_dump_regs); | ||
| 901 | |||
| 902 | venc_probe_pdata(pdev); | ||
| 903 | |||
| 827 | return 0; | 904 | return 0; |
| 828 | 905 | ||
| 829 | err_reg_panel_driver: | 906 | err_reg_panel_driver: |
| @@ -833,12 +910,15 @@ err_runtime_get: | |||
| 833 | return r; | 910 | return r; |
| 834 | } | 911 | } |
| 835 | 912 | ||
| 836 | static int omap_venchw_remove(struct platform_device *pdev) | 913 | static int __exit omap_venchw_remove(struct platform_device *pdev) |
| 837 | { | 914 | { |
| 915 | omap_dss_unregister_child_devices(&pdev->dev); | ||
| 916 | |||
| 838 | if (venc.vdda_dac_reg != NULL) { | 917 | if (venc.vdda_dac_reg != NULL) { |
| 839 | regulator_put(venc.vdda_dac_reg); | 918 | regulator_put(venc.vdda_dac_reg); |
| 840 | venc.vdda_dac_reg = NULL; | 919 | venc.vdda_dac_reg = NULL; |
| 841 | } | 920 | } |
| 921 | |||
| 842 | omap_dss_unregister_driver(&venc_driver); | 922 | omap_dss_unregister_driver(&venc_driver); |
| 843 | 923 | ||
| 844 | pm_runtime_disable(&pdev->dev); | 924 | pm_runtime_disable(&pdev->dev); |
| @@ -853,7 +933,6 @@ static int venc_runtime_suspend(struct device *dev) | |||
| 853 | clk_disable(venc.tv_dac_clk); | 933 | clk_disable(venc.tv_dac_clk); |
| 854 | 934 | ||
| 855 | dispc_runtime_put(); | 935 | dispc_runtime_put(); |
| 856 | dss_runtime_put(); | ||
| 857 | 936 | ||
| 858 | return 0; | 937 | return 0; |
| 859 | } | 938 | } |
| @@ -862,23 +941,14 @@ static int venc_runtime_resume(struct device *dev) | |||
| 862 | { | 941 | { |
| 863 | int r; | 942 | int r; |
| 864 | 943 | ||
| 865 | r = dss_runtime_get(); | ||
| 866 | if (r < 0) | ||
| 867 | goto err_get_dss; | ||
| 868 | |||
| 869 | r = dispc_runtime_get(); | 944 | r = dispc_runtime_get(); |
| 870 | if (r < 0) | 945 | if (r < 0) |
| 871 | goto err_get_dispc; | 946 | return r; |
| 872 | 947 | ||
| 873 | if (venc.tv_dac_clk) | 948 | if (venc.tv_dac_clk) |
| 874 | clk_enable(venc.tv_dac_clk); | 949 | clk_enable(venc.tv_dac_clk); |
| 875 | 950 | ||
| 876 | return 0; | 951 | return 0; |
| 877 | |||
| 878 | err_get_dispc: | ||
| 879 | dss_runtime_put(); | ||
| 880 | err_get_dss: | ||
| 881 | return r; | ||
| 882 | } | 952 | } |
| 883 | 953 | ||
| 884 | static const struct dev_pm_ops venc_pm_ops = { | 954 | static const struct dev_pm_ops venc_pm_ops = { |
| @@ -887,8 +957,7 @@ static const struct dev_pm_ops venc_pm_ops = { | |||
| 887 | }; | 957 | }; |
| 888 | 958 | ||
| 889 | static struct platform_driver omap_venchw_driver = { | 959 | static struct platform_driver omap_venchw_driver = { |
| 890 | .probe = omap_venchw_probe, | 960 | .remove = __exit_p(omap_venchw_remove), |
| 891 | .remove = omap_venchw_remove, | ||
| 892 | .driver = { | 961 | .driver = { |
| 893 | .name = "omapdss_venc", | 962 | .name = "omapdss_venc", |
| 894 | .owner = THIS_MODULE, | 963 | .owner = THIS_MODULE, |
| @@ -896,18 +965,18 @@ static struct platform_driver omap_venchw_driver = { | |||
| 896 | }, | 965 | }, |
| 897 | }; | 966 | }; |
| 898 | 967 | ||
| 899 | int venc_init_platform_driver(void) | 968 | int __init venc_init_platform_driver(void) |
| 900 | { | 969 | { |
| 901 | if (cpu_is_omap44xx()) | 970 | if (cpu_is_omap44xx()) |
| 902 | return 0; | 971 | return 0; |
| 903 | 972 | ||
| 904 | return platform_driver_register(&omap_venchw_driver); | 973 | return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe); |
| 905 | } | 974 | } |
| 906 | 975 | ||
| 907 | void venc_uninit_platform_driver(void) | 976 | void __exit venc_uninit_platform_driver(void) |
| 908 | { | 977 | { |
| 909 | if (cpu_is_omap44xx()) | 978 | if (cpu_is_omap44xx()) |
| 910 | return; | 979 | return; |
| 911 | 980 | ||
| 912 | return platform_driver_unregister(&omap_venchw_driver); | 981 | platform_driver_unregister(&omap_venchw_driver); |
| 913 | } | 982 | } |
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 6a09ef87e14f..c6cf372d22c5 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c | |||
| @@ -70,7 +70,7 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
| 70 | 70 | ||
| 71 | DBG("omapfb_setup_plane\n"); | 71 | DBG("omapfb_setup_plane\n"); |
| 72 | 72 | ||
| 73 | if (ofbi->num_overlays != 1) { | 73 | if (ofbi->num_overlays == 0) { |
| 74 | r = -EINVAL; | 74 | r = -EINVAL; |
| 75 | goto out; | 75 | goto out; |
| 76 | } | 76 | } |
| @@ -185,7 +185,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
| 185 | { | 185 | { |
| 186 | struct omapfb_info *ofbi = FB2OFB(fbi); | 186 | struct omapfb_info *ofbi = FB2OFB(fbi); |
| 187 | 187 | ||
| 188 | if (ofbi->num_overlays != 1) { | 188 | if (ofbi->num_overlays == 0) { |
| 189 | memset(pi, 0, sizeof(*pi)); | 189 | memset(pi, 0, sizeof(*pi)); |
| 190 | } else { | 190 | } else { |
| 191 | struct omap_overlay *ovl; | 191 | struct omap_overlay *ovl; |
| @@ -225,6 +225,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
| 225 | down_write_nested(&rg->lock, rg->id); | 225 | down_write_nested(&rg->lock, rg->id); |
| 226 | atomic_inc(&rg->lock_count); | 226 | atomic_inc(&rg->lock_count); |
| 227 | 227 | ||
| 228 | if (rg->size == size && rg->type == mi->type) | ||
| 229 | goto out; | ||
| 230 | |||
| 228 | if (atomic_read(&rg->map_count)) { | 231 | if (atomic_read(&rg->map_count)) { |
| 229 | r = -EBUSY; | 232 | r = -EBUSY; |
| 230 | goto out; | 233 | goto out; |
| @@ -247,12 +250,10 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
| 247 | } | 250 | } |
| 248 | } | 251 | } |
| 249 | 252 | ||
| 250 | if (rg->size != size || rg->type != mi->type) { | 253 | r = omapfb_realloc_fbmem(fbi, size, mi->type); |
| 251 | r = omapfb_realloc_fbmem(fbi, size, mi->type); | 254 | if (r) { |
| 252 | if (r) { | 255 | dev_err(fbdev->dev, "realloc fbmem failed\n"); |
| 253 | dev_err(fbdev->dev, "realloc fbmem failed\n"); | 256 | goto out; |
| 254 | goto out; | ||
| 255 | } | ||
| 256 | } | 257 | } |
| 257 | 258 | ||
| 258 | out: | 259 | out: |
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index b00db4068d21..3450ea0966c9 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
| @@ -179,6 +179,7 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot) | |||
| 179 | break; | 179 | break; |
| 180 | default: | 180 | default: |
| 181 | BUG(); | 181 | BUG(); |
| 182 | return 0; | ||
| 182 | } | 183 | } |
| 183 | 184 | ||
| 184 | offset *= vrfb->bytespp; | 185 | offset *= vrfb->bytespp; |
| @@ -1502,7 +1503,7 @@ static int omapfb_parse_vram_param(const char *param, int max_entries, | |||
| 1502 | 1503 | ||
| 1503 | fbnum = simple_strtoul(p, &p, 10); | 1504 | fbnum = simple_strtoul(p, &p, 10); |
| 1504 | 1505 | ||
| 1505 | if (p == param) | 1506 | if (p == start) |
| 1506 | return -EINVAL; | 1507 | return -EINVAL; |
| 1507 | 1508 | ||
| 1508 | if (*p != ':') | 1509 | if (*p != ':') |
| @@ -2307,7 +2308,7 @@ static int omapfb_init_display(struct omapfb2_device *fbdev, | |||
| 2307 | return 0; | 2308 | return 0; |
| 2308 | } | 2309 | } |
| 2309 | 2310 | ||
| 2310 | static int omapfb_probe(struct platform_device *pdev) | 2311 | static int __init omapfb_probe(struct platform_device *pdev) |
| 2311 | { | 2312 | { |
| 2312 | struct omapfb2_device *fbdev = NULL; | 2313 | struct omapfb2_device *fbdev = NULL; |
| 2313 | int r = 0; | 2314 | int r = 0; |
| @@ -2448,7 +2449,7 @@ err0: | |||
| 2448 | return r; | 2449 | return r; |
| 2449 | } | 2450 | } |
| 2450 | 2451 | ||
| 2451 | static int omapfb_remove(struct platform_device *pdev) | 2452 | static int __exit omapfb_remove(struct platform_device *pdev) |
| 2452 | { | 2453 | { |
| 2453 | struct omapfb2_device *fbdev = platform_get_drvdata(pdev); | 2454 | struct omapfb2_device *fbdev = platform_get_drvdata(pdev); |
| 2454 | 2455 | ||
| @@ -2462,8 +2463,7 @@ static int omapfb_remove(struct platform_device *pdev) | |||
| 2462 | } | 2463 | } |
| 2463 | 2464 | ||
| 2464 | static struct platform_driver omapfb_driver = { | 2465 | static struct platform_driver omapfb_driver = { |
| 2465 | .probe = omapfb_probe, | 2466 | .remove = __exit_p(omapfb_remove), |
| 2466 | .remove = omapfb_remove, | ||
| 2467 | .driver = { | 2467 | .driver = { |
| 2468 | .name = "omapfb", | 2468 | .name = "omapfb", |
| 2469 | .owner = THIS_MODULE, | 2469 | .owner = THIS_MODULE, |
| @@ -2474,7 +2474,7 @@ static int __init omapfb_init(void) | |||
| 2474 | { | 2474 | { |
| 2475 | DBG("omapfb_init\n"); | 2475 | DBG("omapfb_init\n"); |
| 2476 | 2476 | ||
| 2477 | if (platform_driver_register(&omapfb_driver)) { | 2477 | if (platform_driver_probe(&omapfb_driver, omapfb_probe)) { |
| 2478 | printk(KERN_ERR "failed to register omapfb driver\n"); | 2478 | printk(KERN_ERR "failed to register omapfb driver\n"); |
| 2479 | return -ENODEV; | 2479 | return -ENODEV; |
| 2480 | } | 2480 | } |
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h index c0bdc9b54ecf..30361a09aecd 100644 --- a/drivers/video/omap2/omapfb/omapfb.h +++ b/drivers/video/omap2/omapfb/omapfb.h | |||
| @@ -166,6 +166,7 @@ static inline struct omapfb_display_data *get_display_data( | |||
| 166 | 166 | ||
| 167 | /* This should never happen */ | 167 | /* This should never happen */ |
| 168 | BUG(); | 168 | BUG(); |
| 169 | return NULL; | ||
| 169 | } | 170 | } |
| 170 | 171 | ||
| 171 | static inline void omapfb_lock(struct omapfb2_device *fbdev) | 172 | static inline void omapfb_lock(struct omapfb2_device *fbdev) |
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c index 4e5b960c32c8..7e990220ad2a 100644 --- a/drivers/video/omap2/vrfb.c +++ b/drivers/video/omap2/vrfb.c | |||
| @@ -179,8 +179,10 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, | |||
| 179 | pixel_size_exp = 2; | 179 | pixel_size_exp = 2; |
| 180 | else if (bytespp == 2) | 180 | else if (bytespp == 2) |
| 181 | pixel_size_exp = 1; | 181 | pixel_size_exp = 1; |
| 182 | else | 182 | else { |
| 183 | BUG(); | 183 | BUG(); |
| 184 | return; | ||
| 185 | } | ||
| 184 | 186 | ||
| 185 | vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp; | 187 | vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp; |
| 186 | vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT); | 188 | vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT); |
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c index 1d71c08a818f..0b4ae0cebeda 100644 --- a/drivers/video/pxa3xx-gcu.c +++ b/drivers/video/pxa3xx-gcu.c | |||
| @@ -316,12 +316,9 @@ pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv) | |||
| 316 | ret = wait_event_interruptible_timeout(priv->wait_idle, | 316 | ret = wait_event_interruptible_timeout(priv->wait_idle, |
| 317 | !priv->shared->hw_running, HZ*4); | 317 | !priv->shared->hw_running, HZ*4); |
| 318 | 318 | ||
| 319 | if (ret < 0) | 319 | if (ret != 0) |
| 320 | break; | 320 | break; |
| 321 | 321 | ||
| 322 | if (ret > 0) | ||
| 323 | continue; | ||
| 324 | |||
| 325 | if (gc_readl(priv, REG_GCRBEXHR) == rbexhr && | 322 | if (gc_readl(priv, REG_GCRBEXHR) == rbexhr && |
| 326 | priv->shared->num_interrupts == num) { | 323 | priv->shared->num_interrupts == num) { |
| 327 | QERROR("TIMEOUT"); | 324 | QERROR("TIMEOUT"); |
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index f3105160bf98..5f9d8e69029e 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
| @@ -47,7 +47,7 @@ | |||
| 47 | #ifdef CONFIG_FB_S3C_DEBUG_REGWRITE | 47 | #ifdef CONFIG_FB_S3C_DEBUG_REGWRITE |
| 48 | #undef writel | 48 | #undef writel |
| 49 | #define writel(v, r) do { \ | 49 | #define writel(v, r) do { \ |
| 50 | printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \ | 50 | pr_debug("%s: %08x => %p\n", __func__, (unsigned int)v, r); \ |
| 51 | __raw_writel(v, r); \ | 51 | __raw_writel(v, r); \ |
| 52 | } while (0) | 52 | } while (0) |
| 53 | #endif /* FB_S3C_DEBUG_REGWRITE */ | 53 | #endif /* FB_S3C_DEBUG_REGWRITE */ |
| @@ -495,7 +495,6 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
| 495 | u32 alpha = 0; | 495 | u32 alpha = 0; |
| 496 | u32 data; | 496 | u32 data; |
| 497 | u32 pagewidth; | 497 | u32 pagewidth; |
| 498 | int clkdiv; | ||
| 499 | 498 | ||
| 500 | dev_dbg(sfb->dev, "setting framebuffer parameters\n"); | 499 | dev_dbg(sfb->dev, "setting framebuffer parameters\n"); |
| 501 | 500 | ||
| @@ -532,48 +531,9 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
| 532 | /* disable the window whilst we update it */ | 531 | /* disable the window whilst we update it */ |
| 533 | writel(0, regs + WINCON(win_no)); | 532 | writel(0, regs + WINCON(win_no)); |
| 534 | 533 | ||
| 535 | /* use platform specified window as the basis for the lcd timings */ | 534 | if (!sfb->output_on) |
| 536 | |||
| 537 | if (win_no == sfb->pdata->default_win) { | ||
| 538 | clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); | ||
| 539 | |||
| 540 | data = sfb->pdata->vidcon0; | ||
| 541 | data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); | ||
| 542 | |||
| 543 | if (clkdiv > 1) | ||
| 544 | data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR; | ||
| 545 | else | ||
| 546 | data &= ~VIDCON0_CLKDIR; /* 1:1 clock */ | ||
| 547 | |||
| 548 | /* write the timing data to the panel */ | ||
| 549 | |||
| 550 | if (sfb->variant.is_2443) | ||
| 551 | data |= (1 << 5); | ||
| 552 | |||
| 553 | writel(data, regs + VIDCON0); | ||
| 554 | |||
| 555 | s3c_fb_enable(sfb, 1); | 535 | s3c_fb_enable(sfb, 1); |
| 556 | 536 | ||
| 557 | data = VIDTCON0_VBPD(var->upper_margin - 1) | | ||
| 558 | VIDTCON0_VFPD(var->lower_margin - 1) | | ||
| 559 | VIDTCON0_VSPW(var->vsync_len - 1); | ||
| 560 | |||
| 561 | writel(data, regs + sfb->variant.vidtcon); | ||
| 562 | |||
| 563 | data = VIDTCON1_HBPD(var->left_margin - 1) | | ||
| 564 | VIDTCON1_HFPD(var->right_margin - 1) | | ||
| 565 | VIDTCON1_HSPW(var->hsync_len - 1); | ||
| 566 | |||
| 567 | /* VIDTCON1 */ | ||
| 568 | writel(data, regs + sfb->variant.vidtcon + 4); | ||
| 569 | |||
| 570 | data = VIDTCON2_LINEVAL(var->yres - 1) | | ||
| 571 | VIDTCON2_HOZVAL(var->xres - 1) | | ||
| 572 | VIDTCON2_LINEVAL_E(var->yres - 1) | | ||
| 573 | VIDTCON2_HOZVAL_E(var->xres - 1); | ||
| 574 | writel(data, regs + sfb->variant.vidtcon + 8); | ||
| 575 | } | ||
| 576 | |||
| 577 | /* write the buffer address */ | 537 | /* write the buffer address */ |
| 578 | 538 | ||
| 579 | /* start and end registers stride is 8 */ | 539 | /* start and end registers stride is 8 */ |
| @@ -839,6 +799,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) | |||
| 839 | struct s3c_fb *sfb = win->parent; | 799 | struct s3c_fb *sfb = win->parent; |
| 840 | unsigned int index = win->index; | 800 | unsigned int index = win->index; |
| 841 | u32 wincon; | 801 | u32 wincon; |
| 802 | u32 output_on = sfb->output_on; | ||
| 842 | 803 | ||
| 843 | dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); | 804 | dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); |
| 844 | 805 | ||
| @@ -877,34 +838,18 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) | |||
| 877 | 838 | ||
| 878 | shadow_protect_win(win, 1); | 839 | shadow_protect_win(win, 1); |
| 879 | writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4)); | 840 | writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4)); |
| 880 | shadow_protect_win(win, 0); | ||
| 881 | 841 | ||
| 882 | /* Check the enabled state to see if we need to be running the | 842 | /* Check the enabled state to see if we need to be running the |
| 883 | * main LCD interface, as if there are no active windows then | 843 | * main LCD interface, as if there are no active windows then |
| 884 | * it is highly likely that we also do not need to output | 844 | * it is highly likely that we also do not need to output |
| 885 | * anything. | 845 | * anything. |
| 886 | */ | 846 | */ |
| 887 | 847 | s3c_fb_enable(sfb, sfb->enabled ? 1 : 0); | |
| 888 | /* We could do something like the following code, but the current | 848 | shadow_protect_win(win, 0); |
| 889 | * system of using framebuffer events means that we cannot make | ||
| 890 | * the distinction between just window 0 being inactive and all | ||
| 891 | * the windows being down. | ||
| 892 | * | ||
| 893 | * s3c_fb_enable(sfb, sfb->enabled ? 1 : 0); | ||
| 894 | */ | ||
| 895 | |||
| 896 | /* we're stuck with this until we can do something about overriding | ||
| 897 | * the power control using the blanking event for a single fb. | ||
| 898 | */ | ||
| 899 | if (index == sfb->pdata->default_win) { | ||
| 900 | shadow_protect_win(win, 1); | ||
| 901 | s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); | ||
| 902 | shadow_protect_win(win, 0); | ||
| 903 | } | ||
| 904 | 849 | ||
| 905 | pm_runtime_put_sync(sfb->dev); | 850 | pm_runtime_put_sync(sfb->dev); |
| 906 | 851 | ||
| 907 | return 0; | 852 | return output_on == sfb->output_on; |
| 908 | } | 853 | } |
| 909 | 854 | ||
| 910 | /** | 855 | /** |
| @@ -1111,7 +1056,7 @@ static struct fb_ops s3c_fb_ops = { | |||
| 1111 | * | 1056 | * |
| 1112 | * Calculate the pixel clock when none has been given through platform data. | 1057 | * Calculate the pixel clock when none has been given through platform data. |
| 1113 | */ | 1058 | */ |
| 1114 | static void __devinit s3c_fb_missing_pixclock(struct fb_videomode *mode) | 1059 | static void s3c_fb_missing_pixclock(struct fb_videomode *mode) |
| 1115 | { | 1060 | { |
| 1116 | u64 pixclk = 1000000000000ULL; | 1061 | u64 pixclk = 1000000000000ULL; |
| 1117 | u32 div; | 1062 | u32 div; |
| @@ -1144,11 +1089,11 @@ static int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb, | |||
| 1144 | 1089 | ||
| 1145 | dev_dbg(sfb->dev, "allocating memory for display\n"); | 1090 | dev_dbg(sfb->dev, "allocating memory for display\n"); |
| 1146 | 1091 | ||
| 1147 | real_size = windata->win_mode.xres * windata->win_mode.yres; | 1092 | real_size = windata->xres * windata->yres; |
| 1148 | virt_size = windata->virtual_x * windata->virtual_y; | 1093 | virt_size = windata->virtual_x * windata->virtual_y; |
| 1149 | 1094 | ||
| 1150 | dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n", | 1095 | dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n", |
| 1151 | real_size, windata->win_mode.xres, windata->win_mode.yres, | 1096 | real_size, windata->xres, windata->yres, |
| 1152 | virt_size, windata->virtual_x, windata->virtual_y); | 1097 | virt_size, windata->virtual_x, windata->virtual_y); |
| 1153 | 1098 | ||
| 1154 | size = (real_size > virt_size) ? real_size : virt_size; | 1099 | size = (real_size > virt_size) ? real_size : virt_size; |
| @@ -1230,7 +1175,7 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
| 1230 | struct s3c_fb_win **res) | 1175 | struct s3c_fb_win **res) |
| 1231 | { | 1176 | { |
| 1232 | struct fb_var_screeninfo *var; | 1177 | struct fb_var_screeninfo *var; |
| 1233 | struct fb_videomode *initmode; | 1178 | struct fb_videomode initmode; |
| 1234 | struct s3c_fb_pd_win *windata; | 1179 | struct s3c_fb_pd_win *windata; |
| 1235 | struct s3c_fb_win *win; | 1180 | struct s3c_fb_win *win; |
| 1236 | struct fb_info *fbinfo; | 1181 | struct fb_info *fbinfo; |
| @@ -1251,11 +1196,11 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
| 1251 | } | 1196 | } |
| 1252 | 1197 | ||
| 1253 | windata = sfb->pdata->win[win_no]; | 1198 | windata = sfb->pdata->win[win_no]; |
| 1254 | initmode = &windata->win_mode; | 1199 | initmode = *sfb->pdata->vtiming; |
| 1255 | 1200 | ||
| 1256 | WARN_ON(windata->max_bpp == 0); | 1201 | WARN_ON(windata->max_bpp == 0); |
| 1257 | WARN_ON(windata->win_mode.xres == 0); | 1202 | WARN_ON(windata->xres == 0); |
| 1258 | WARN_ON(windata->win_mode.yres == 0); | 1203 | WARN_ON(windata->yres == 0); |
| 1259 | 1204 | ||
| 1260 | win = fbinfo->par; | 1205 | win = fbinfo->par; |
| 1261 | *res = win; | 1206 | *res = win; |
| @@ -1294,7 +1239,9 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
| 1294 | } | 1239 | } |
| 1295 | 1240 | ||
| 1296 | /* setup the initial video mode from the window */ | 1241 | /* setup the initial video mode from the window */ |
| 1297 | fb_videomode_to_var(&fbinfo->var, initmode); | 1242 | initmode.xres = windata->xres; |
| 1243 | initmode.yres = windata->yres; | ||
| 1244 | fb_videomode_to_var(&fbinfo->var, &initmode); | ||
| 1298 | 1245 | ||
| 1299 | fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; | 1246 | fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; |
| 1300 | fbinfo->fix.accel = FB_ACCEL_NONE; | 1247 | fbinfo->fix.accel = FB_ACCEL_NONE; |
| @@ -1339,6 +1286,53 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
| 1339 | } | 1286 | } |
| 1340 | 1287 | ||
| 1341 | /** | 1288 | /** |
| 1289 | * s3c_fb_set_rgb_timing() - set video timing for rgb interface. | ||
| 1290 | * @sfb: The base resources for the hardware. | ||
| 1291 | * | ||
| 1292 | * Set horizontal and vertical lcd rgb interface timing. | ||
| 1293 | */ | ||
| 1294 | static void s3c_fb_set_rgb_timing(struct s3c_fb *sfb) | ||
| 1295 | { | ||
| 1296 | struct fb_videomode *vmode = sfb->pdata->vtiming; | ||
| 1297 | void __iomem *regs = sfb->regs; | ||
| 1298 | int clkdiv; | ||
| 1299 | u32 data; | ||
| 1300 | |||
| 1301 | if (!vmode->pixclock) | ||
| 1302 | s3c_fb_missing_pixclock(vmode); | ||
| 1303 | |||
| 1304 | clkdiv = s3c_fb_calc_pixclk(sfb, vmode->pixclock); | ||
| 1305 | |||
| 1306 | data = sfb->pdata->vidcon0; | ||
| 1307 | data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); | ||
| 1308 | |||
| 1309 | if (clkdiv > 1) | ||
| 1310 | data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR; | ||
| 1311 | else | ||
| 1312 | data &= ~VIDCON0_CLKDIR; /* 1:1 clock */ | ||
| 1313 | |||
| 1314 | if (sfb->variant.is_2443) | ||
| 1315 | data |= (1 << 5); | ||
| 1316 | writel(data, regs + VIDCON0); | ||
| 1317 | |||
| 1318 | data = VIDTCON0_VBPD(vmode->upper_margin - 1) | | ||
| 1319 | VIDTCON0_VFPD(vmode->lower_margin - 1) | | ||
| 1320 | VIDTCON0_VSPW(vmode->vsync_len - 1); | ||
| 1321 | writel(data, regs + sfb->variant.vidtcon); | ||
| 1322 | |||
| 1323 | data = VIDTCON1_HBPD(vmode->left_margin - 1) | | ||
| 1324 | VIDTCON1_HFPD(vmode->right_margin - 1) | | ||
| 1325 | VIDTCON1_HSPW(vmode->hsync_len - 1); | ||
| 1326 | writel(data, regs + sfb->variant.vidtcon + 4); | ||
| 1327 | |||
| 1328 | data = VIDTCON2_LINEVAL(vmode->yres - 1) | | ||
| 1329 | VIDTCON2_HOZVAL(vmode->xres - 1) | | ||
| 1330 | VIDTCON2_LINEVAL_E(vmode->yres - 1) | | ||
| 1331 | VIDTCON2_HOZVAL_E(vmode->xres - 1); | ||
| 1332 | writel(data, regs + sfb->variant.vidtcon + 8); | ||
| 1333 | } | ||
| 1334 | |||
| 1335 | /** | ||
| 1342 | * s3c_fb_clear_win() - clear hardware window registers. | 1336 | * s3c_fb_clear_win() - clear hardware window registers. |
| 1343 | * @sfb: The base resources for the hardware. | 1337 | * @sfb: The base resources for the hardware. |
| 1344 | * @win: The window to process. | 1338 | * @win: The window to process. |
| @@ -1481,15 +1475,14 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
| 1481 | writel(0xffffff, regs + WKEYCON1); | 1475 | writel(0xffffff, regs + WKEYCON1); |
| 1482 | } | 1476 | } |
| 1483 | 1477 | ||
| 1478 | s3c_fb_set_rgb_timing(sfb); | ||
| 1479 | |||
| 1484 | /* we have the register setup, start allocating framebuffers */ | 1480 | /* we have the register setup, start allocating framebuffers */ |
| 1485 | 1481 | ||
| 1486 | for (win = 0; win < fbdrv->variant.nr_windows; win++) { | 1482 | for (win = 0; win < fbdrv->variant.nr_windows; win++) { |
| 1487 | if (!pd->win[win]) | 1483 | if (!pd->win[win]) |
| 1488 | continue; | 1484 | continue; |
| 1489 | 1485 | ||
| 1490 | if (!pd->win[win]->win_mode.pixclock) | ||
| 1491 | s3c_fb_missing_pixclock(&pd->win[win]->win_mode); | ||
| 1492 | |||
| 1493 | ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win], | 1486 | ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win], |
| 1494 | &sfb->windows[win]); | 1487 | &sfb->windows[win]); |
| 1495 | if (ret < 0) { | 1488 | if (ret < 0) { |
| @@ -1564,6 +1557,8 @@ static int s3c_fb_suspend(struct device *dev) | |||
| 1564 | struct s3c_fb_win *win; | 1557 | struct s3c_fb_win *win; |
| 1565 | int win_no; | 1558 | int win_no; |
| 1566 | 1559 | ||
| 1560 | pm_runtime_get_sync(sfb->dev); | ||
| 1561 | |||
| 1567 | for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) { | 1562 | for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) { |
| 1568 | win = sfb->windows[win_no]; | 1563 | win = sfb->windows[win_no]; |
| 1569 | if (!win) | 1564 | if (!win) |
| @@ -1577,6 +1572,9 @@ static int s3c_fb_suspend(struct device *dev) | |||
| 1577 | clk_disable(sfb->lcd_clk); | 1572 | clk_disable(sfb->lcd_clk); |
| 1578 | 1573 | ||
| 1579 | clk_disable(sfb->bus_clk); | 1574 | clk_disable(sfb->bus_clk); |
| 1575 | |||
| 1576 | pm_runtime_put_sync(sfb->dev); | ||
| 1577 | |||
| 1580 | return 0; | 1578 | return 0; |
| 1581 | } | 1579 | } |
| 1582 | 1580 | ||
| @@ -1589,6 +1587,8 @@ static int s3c_fb_resume(struct device *dev) | |||
| 1589 | int win_no; | 1587 | int win_no; |
| 1590 | u32 reg; | 1588 | u32 reg; |
| 1591 | 1589 | ||
| 1590 | pm_runtime_get_sync(sfb->dev); | ||
| 1591 | |||
| 1592 | clk_enable(sfb->bus_clk); | 1592 | clk_enable(sfb->bus_clk); |
| 1593 | 1593 | ||
| 1594 | if (!sfb->variant.has_clksel) | 1594 | if (!sfb->variant.has_clksel) |
| @@ -1623,6 +1623,8 @@ static int s3c_fb_resume(struct device *dev) | |||
| 1623 | shadow_protect_win(win, 0); | 1623 | shadow_protect_win(win, 0); |
| 1624 | } | 1624 | } |
| 1625 | 1625 | ||
| 1626 | s3c_fb_set_rgb_timing(sfb); | ||
| 1627 | |||
| 1626 | /* restore framebuffers */ | 1628 | /* restore framebuffers */ |
| 1627 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { | 1629 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { |
| 1628 | win = sfb->windows[win_no]; | 1630 | win = sfb->windows[win_no]; |
| @@ -1633,6 +1635,8 @@ static int s3c_fb_resume(struct device *dev) | |||
| 1633 | s3c_fb_set_par(win->fbinfo); | 1635 | s3c_fb_set_par(win->fbinfo); |
| 1634 | } | 1636 | } |
| 1635 | 1637 | ||
| 1638 | pm_runtime_put_sync(sfb->dev); | ||
| 1639 | |||
| 1636 | return 0; | 1640 | return 0; |
| 1637 | } | 1641 | } |
| 1638 | #endif | 1642 | #endif |
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index eafb19da2c07..930e550e752a 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | 31 | ||
| 32 | #include "sh_mobile_lcdcfb.h" | 32 | #include "sh_mobile_lcdcfb.h" |
| 33 | 33 | ||
| 34 | /* HDMI Core Control Register (HTOP0) */ | ||
| 34 | #define HDMI_SYSTEM_CTRL 0x00 /* System control */ | 35 | #define HDMI_SYSTEM_CTRL 0x00 /* System control */ |
| 35 | #define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, | 36 | #define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, |
| 36 | bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ | 37 | bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ |
| @@ -201,6 +202,68 @@ | |||
| 201 | #define HDMI_REVISION_ID 0xF1 /* Revision ID */ | 202 | #define HDMI_REVISION_ID 0xF1 /* Revision ID */ |
| 202 | #define HDMI_TEST_MODE 0xFE /* Test mode */ | 203 | #define HDMI_TEST_MODE 0xFE /* Test mode */ |
| 203 | 204 | ||
| 205 | /* HDMI Control Register (HTOP1) */ | ||
| 206 | #define HDMI_HTOP1_TEST_MODE 0x0000 /* Test mode */ | ||
| 207 | #define HDMI_HTOP1_VIDEO_INPUT 0x0008 /* VideoInput */ | ||
| 208 | #define HDMI_HTOP1_CORE_RSTN 0x000C /* CoreResetn */ | ||
| 209 | #define HDMI_HTOP1_PLLBW 0x0018 /* PLLBW */ | ||
| 210 | #define HDMI_HTOP1_CLK_TO_PHY 0x001C /* Clk to Phy */ | ||
| 211 | #define HDMI_HTOP1_VIDEO_INPUT2 0x0020 /* VideoInput2 */ | ||
| 212 | #define HDMI_HTOP1_TISEMP0_1 0x0024 /* tisemp0-1 */ | ||
| 213 | #define HDMI_HTOP1_TISEMP2_C 0x0028 /* tisemp2-c */ | ||
| 214 | #define HDMI_HTOP1_TISIDRV 0x002C /* tisidrv */ | ||
| 215 | #define HDMI_HTOP1_TISEN 0x0034 /* tisen */ | ||
| 216 | #define HDMI_HTOP1_TISDREN 0x0038 /* tisdren */ | ||
| 217 | #define HDMI_HTOP1_CISRANGE 0x003C /* cisrange */ | ||
| 218 | #define HDMI_HTOP1_ENABLE_SELECTOR 0x0040 /* Enable Selector */ | ||
| 219 | #define HDMI_HTOP1_MACRO_RESET 0x0044 /* Macro reset */ | ||
| 220 | #define HDMI_HTOP1_PLL_CALIBRATION 0x0048 /* PLL calibration */ | ||
| 221 | #define HDMI_HTOP1_RE_CALIBRATION 0x004C /* Re-calibration */ | ||
| 222 | #define HDMI_HTOP1_CURRENT 0x0050 /* Current */ | ||
| 223 | #define HDMI_HTOP1_PLL_LOCK_DETECT 0x0054 /* PLL lock detect */ | ||
| 224 | #define HDMI_HTOP1_PHY_TEST_MODE 0x0058 /* PHY Test Mode */ | ||
| 225 | #define HDMI_HTOP1_CLK_SET 0x0080 /* Clock Set */ | ||
| 226 | #define HDMI_HTOP1_DDC_FAIL_SAFE 0x0084 /* DDC fail safe */ | ||
| 227 | #define HDMI_HTOP1_PRBS 0x0088 /* PRBS */ | ||
| 228 | #define HDMI_HTOP1_EDID_AINC_CONTROL 0x008C /* EDID ainc Control */ | ||
| 229 | #define HDMI_HTOP1_HTOP_DCL_MODE 0x00FC /* Deep Coloer Mode */ | ||
| 230 | #define HDMI_HTOP1_HTOP_DCL_FRC_COEF0 0x0100 /* Deep Color:FRC COEF0 */ | ||
| 231 | #define HDMI_HTOP1_HTOP_DCL_FRC_COEF1 0x0104 /* Deep Color:FRC COEF1 */ | ||
| 232 | #define HDMI_HTOP1_HTOP_DCL_FRC_COEF2 0x0108 /* Deep Color:FRC COEF2 */ | ||
| 233 | #define HDMI_HTOP1_HTOP_DCL_FRC_COEF3 0x010C /* Deep Color:FRC COEF3 */ | ||
| 234 | #define HDMI_HTOP1_HTOP_DCL_FRC_COEF0_C 0x0110 /* Deep Color:FRC COEF0C */ | ||
| 235 | #define HDMI_HTOP1_HTOP_DCL_FRC_COEF1_C 0x0114 /* Deep Color:FRC COEF1C */ | ||
| 236 | #define HDMI_HTOP1_HTOP_DCL_FRC_COEF2_C 0x0118 /* Deep Color:FRC COEF2C */ | ||
| 237 | #define HDMI_HTOP1_HTOP_DCL_FRC_COEF3_C 0x011C /* Deep Color:FRC COEF3C */ | ||
| 238 | #define HDMI_HTOP1_HTOP_DCL_FRC_MODE 0x0120 /* Deep Color:FRC Mode */ | ||
| 239 | #define HDMI_HTOP1_HTOP_DCL_RECT_START1 0x0124 /* Deep Color:Rect Start1 */ | ||
| 240 | #define HDMI_HTOP1_HTOP_DCL_RECT_SIZE1 0x0128 /* Deep Color:Rect Size1 */ | ||
| 241 | #define HDMI_HTOP1_HTOP_DCL_RECT_START2 0x012C /* Deep Color:Rect Start2 */ | ||
| 242 | #define HDMI_HTOP1_HTOP_DCL_RECT_SIZE2 0x0130 /* Deep Color:Rect Size2 */ | ||
| 243 | #define HDMI_HTOP1_HTOP_DCL_RECT_START3 0x0134 /* Deep Color:Rect Start3 */ | ||
| 244 | #define HDMI_HTOP1_HTOP_DCL_RECT_SIZE3 0x0138 /* Deep Color:Rect Size3 */ | ||
| 245 | #define HDMI_HTOP1_HTOP_DCL_RECT_START4 0x013C /* Deep Color:Rect Start4 */ | ||
| 246 | #define HDMI_HTOP1_HTOP_DCL_RECT_SIZE4 0x0140 /* Deep Color:Rect Size4 */ | ||
| 247 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1 0x0144 /* Deep Color:Fil Para Y1_1 */ | ||
| 248 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2 0x0148 /* Deep Color:Fil Para Y1_2 */ | ||
| 249 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1 0x014C /* Deep Color:Fil Para CB1_1 */ | ||
| 250 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2 0x0150 /* Deep Color:Fil Para CB1_2 */ | ||
| 251 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1 0x0154 /* Deep Color:Fil Para CR1_1 */ | ||
| 252 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2 0x0158 /* Deep Color:Fil Para CR1_2 */ | ||
| 253 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1 0x015C /* Deep Color:Fil Para Y2_1 */ | ||
| 254 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2 0x0160 /* Deep Color:Fil Para Y2_2 */ | ||
| 255 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1 0x0164 /* Deep Color:Fil Para CB2_1 */ | ||
| 256 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2 0x0168 /* Deep Color:Fil Para CB2_2 */ | ||
| 257 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1 0x016C /* Deep Color:Fil Para CR2_1 */ | ||
| 258 | #define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2 0x0170 /* Deep Color:Fil Para CR2_2 */ | ||
| 259 | #define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1 0x0174 /* Deep Color:Cor Para Y1 */ | ||
| 260 | #define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1 0x0178 /* Deep Color:Cor Para CB1 */ | ||
| 261 | #define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1 0x017C /* Deep Color:Cor Para CR1 */ | ||
| 262 | #define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2 0x0180 /* Deep Color:Cor Para Y2 */ | ||
| 263 | #define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2 0x0184 /* Deep Color:Cor Para CB2 */ | ||
| 264 | #define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2 0x0188 /* Deep Color:Cor Para CR2 */ | ||
| 265 | #define HDMI_HTOP1_EDID_DATA_READ 0x0200 /* EDID Data Read 128Byte:0x03FC */ | ||
| 266 | |||
| 204 | enum hotplug_state { | 267 | enum hotplug_state { |
| 205 | HDMI_HOTPLUG_DISCONNECTED, | 268 | HDMI_HOTPLUG_DISCONNECTED, |
| 206 | HDMI_HOTPLUG_CONNECTED, | 269 | HDMI_HOTPLUG_CONNECTED, |
| @@ -211,6 +274,7 @@ struct sh_hdmi { | |||
| 211 | struct sh_mobile_lcdc_entity entity; | 274 | struct sh_mobile_lcdc_entity entity; |
| 212 | 275 | ||
| 213 | void __iomem *base; | 276 | void __iomem *base; |
| 277 | void __iomem *htop1; | ||
| 214 | enum hotplug_state hp_state; /* hot-plug status */ | 278 | enum hotplug_state hp_state; /* hot-plug status */ |
| 215 | u8 preprogrammed_vic; /* use a pre-programmed VIC or | 279 | u8 preprogrammed_vic; /* use a pre-programmed VIC or |
| 216 | the external mode */ | 280 | the external mode */ |
| @@ -222,20 +286,66 @@ struct sh_hdmi { | |||
| 222 | struct delayed_work edid_work; | 286 | struct delayed_work edid_work; |
| 223 | struct fb_videomode mode; | 287 | struct fb_videomode mode; |
| 224 | struct fb_monspecs monspec; | 288 | struct fb_monspecs monspec; |
| 289 | |||
| 290 | /* register access functions */ | ||
| 291 | void (*write)(struct sh_hdmi *hdmi, u8 data, u8 reg); | ||
| 292 | u8 (*read)(struct sh_hdmi *hdmi, u8 reg); | ||
| 225 | }; | 293 | }; |
| 226 | 294 | ||
| 227 | #define entity_to_sh_hdmi(e) container_of(e, struct sh_hdmi, entity) | 295 | #define entity_to_sh_hdmi(e) container_of(e, struct sh_hdmi, entity) |
| 228 | 296 | ||
| 229 | static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) | 297 | static void __hdmi_write8(struct sh_hdmi *hdmi, u8 data, u8 reg) |
| 230 | { | 298 | { |
| 231 | iowrite8(data, hdmi->base + reg); | 299 | iowrite8(data, hdmi->base + reg); |
| 232 | } | 300 | } |
| 233 | 301 | ||
| 234 | static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg) | 302 | static u8 __hdmi_read8(struct sh_hdmi *hdmi, u8 reg) |
| 235 | { | 303 | { |
| 236 | return ioread8(hdmi->base + reg); | 304 | return ioread8(hdmi->base + reg); |
| 237 | } | 305 | } |
| 238 | 306 | ||
| 307 | static void __hdmi_write32(struct sh_hdmi *hdmi, u8 data, u8 reg) | ||
| 308 | { | ||
| 309 | iowrite32((u32)data, hdmi->base + (reg * 4)); | ||
| 310 | udelay(100); | ||
| 311 | } | ||
| 312 | |||
| 313 | static u8 __hdmi_read32(struct sh_hdmi *hdmi, u8 reg) | ||
| 314 | { | ||
| 315 | return (u8)ioread32(hdmi->base + (reg * 4)); | ||
| 316 | } | ||
| 317 | |||
| 318 | static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) | ||
| 319 | { | ||
| 320 | hdmi->write(hdmi, data, reg); | ||
| 321 | } | ||
| 322 | |||
| 323 | static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg) | ||
| 324 | { | ||
| 325 | return hdmi->read(hdmi, reg); | ||
| 326 | } | ||
| 327 | |||
| 328 | static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg) | ||
| 329 | { | ||
| 330 | u8 val = hdmi_read(hdmi, reg); | ||
| 331 | |||
| 332 | val &= ~mask; | ||
| 333 | val |= (data & mask); | ||
| 334 | |||
| 335 | hdmi_write(hdmi, val, reg); | ||
| 336 | } | ||
| 337 | |||
| 338 | static void hdmi_htop1_write(struct sh_hdmi *hdmi, u32 data, u32 reg) | ||
| 339 | { | ||
| 340 | iowrite32(data, hdmi->htop1 + reg); | ||
| 341 | udelay(100); | ||
| 342 | } | ||
| 343 | |||
| 344 | static u32 hdmi_htop1_read(struct sh_hdmi *hdmi, u32 reg) | ||
| 345 | { | ||
| 346 | return ioread32(hdmi->htop1 + reg); | ||
| 347 | } | ||
| 348 | |||
| 239 | /* | 349 | /* |
| 240 | * HDMI sound | 350 | * HDMI sound |
| 241 | */ | 351 | */ |
| @@ -693,11 +803,11 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi) | |||
| 693 | msleep(10); | 803 | msleep(10); |
| 694 | 804 | ||
| 695 | /* PS mode b->d, reset PLLA and PLLB */ | 805 | /* PS mode b->d, reset PLLA and PLLB */ |
| 696 | hdmi_write(hdmi, 0x4C, HDMI_SYSTEM_CTRL); | 806 | hdmi_bit_set(hdmi, 0xFC, 0x4C, HDMI_SYSTEM_CTRL); |
| 697 | 807 | ||
| 698 | udelay(10); | 808 | udelay(10); |
| 699 | 809 | ||
| 700 | hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL); | 810 | hdmi_bit_set(hdmi, 0xFC, 0x40, HDMI_SYSTEM_CTRL); |
| 701 | } | 811 | } |
| 702 | 812 | ||
| 703 | static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi, | 813 | static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi, |
| @@ -746,7 +856,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, | |||
| 746 | /* Read EDID */ | 856 | /* Read EDID */ |
| 747 | dev_dbg(hdmi->dev, "Read back EDID code:"); | 857 | dev_dbg(hdmi->dev, "Read back EDID code:"); |
| 748 | for (i = 0; i < 128; i++) { | 858 | for (i = 0; i < 128; i++) { |
| 749 | edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); | 859 | edid[i] = (hdmi->htop1) ? |
| 860 | (u8)hdmi_htop1_read(hdmi, HDMI_HTOP1_EDID_DATA_READ + (i * 4)) : | ||
| 861 | hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); | ||
| 750 | #ifdef DEBUG | 862 | #ifdef DEBUG |
| 751 | if ((i % 16) == 0) { | 863 | if ((i % 16) == 0) { |
| 752 | printk(KERN_CONT "\n"); | 864 | printk(KERN_CONT "\n"); |
| @@ -917,13 +1029,13 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) | |||
| 917 | u8 status1, status2, mask1, mask2; | 1029 | u8 status1, status2, mask1, mask2; |
| 918 | 1030 | ||
| 919 | /* mode_b and PLLA and PLLB reset */ | 1031 | /* mode_b and PLLA and PLLB reset */ |
| 920 | hdmi_write(hdmi, 0x2C, HDMI_SYSTEM_CTRL); | 1032 | hdmi_bit_set(hdmi, 0xFC, 0x2C, HDMI_SYSTEM_CTRL); |
| 921 | 1033 | ||
| 922 | /* How long shall reset be held? */ | 1034 | /* How long shall reset be held? */ |
| 923 | udelay(10); | 1035 | udelay(10); |
| 924 | 1036 | ||
| 925 | /* mode_b and PLLA and PLLB reset release */ | 1037 | /* mode_b and PLLA and PLLB reset release */ |
| 926 | hdmi_write(hdmi, 0x20, HDMI_SYSTEM_CTRL); | 1038 | hdmi_bit_set(hdmi, 0xFC, 0x20, HDMI_SYSTEM_CTRL); |
| 927 | 1039 | ||
| 928 | status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1); | 1040 | status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1); |
| 929 | status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2); | 1041 | status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2); |
| @@ -1001,7 +1113,7 @@ static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity) | |||
| 1001 | */ | 1113 | */ |
| 1002 | if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { | 1114 | if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { |
| 1003 | /* PS mode d->e. All functions are active */ | 1115 | /* PS mode d->e. All functions are active */ |
| 1004 | hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); | 1116 | hdmi_bit_set(hdmi, 0xFC, 0x80, HDMI_SYSTEM_CTRL); |
| 1005 | dev_dbg(hdmi->dev, "HDMI running\n"); | 1117 | dev_dbg(hdmi->dev, "HDMI running\n"); |
| 1006 | } | 1118 | } |
| 1007 | 1119 | ||
| @@ -1016,7 +1128,7 @@ static void sh_hdmi_display_off(struct sh_mobile_lcdc_entity *entity) | |||
| 1016 | 1128 | ||
| 1017 | dev_dbg(hdmi->dev, "%s(%p)\n", __func__, hdmi); | 1129 | dev_dbg(hdmi->dev, "%s(%p)\n", __func__, hdmi); |
| 1018 | /* PS mode e->a */ | 1130 | /* PS mode e->a */ |
| 1019 | hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); | 1131 | hdmi_bit_set(hdmi, 0xFC, 0x10, HDMI_SYSTEM_CTRL); |
| 1020 | } | 1132 | } |
| 1021 | 1133 | ||
| 1022 | static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = { | 1134 | static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = { |
| @@ -1110,10 +1222,58 @@ out: | |||
| 1110 | dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi); | 1222 | dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi); |
| 1111 | } | 1223 | } |
| 1112 | 1224 | ||
| 1225 | static void sh_hdmi_htop1_init(struct sh_hdmi *hdmi) | ||
| 1226 | { | ||
| 1227 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_MODE); | ||
| 1228 | hdmi_htop1_write(hdmi, 0x0000000b, 0x0010); | ||
| 1229 | hdmi_htop1_write(hdmi, 0x00006710, HDMI_HTOP1_HTOP_DCL_FRC_MODE); | ||
| 1230 | hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1); | ||
| 1231 | hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2); | ||
| 1232 | hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1); | ||
| 1233 | hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2); | ||
| 1234 | hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1); | ||
| 1235 | hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2); | ||
| 1236 | hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1); | ||
| 1237 | hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2); | ||
| 1238 | hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1); | ||
| 1239 | hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2); | ||
| 1240 | hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1); | ||
| 1241 | hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2); | ||
| 1242 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1); | ||
| 1243 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1); | ||
| 1244 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1); | ||
| 1245 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2); | ||
| 1246 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2); | ||
| 1247 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2); | ||
| 1248 | hdmi_htop1_write(hdmi, 0x00000008, HDMI_HTOP1_CURRENT); | ||
| 1249 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP0_1); | ||
| 1250 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP2_C); | ||
| 1251 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PHY_TEST_MODE); | ||
| 1252 | hdmi_htop1_write(hdmi, 0x00000081, HDMI_HTOP1_TISIDRV); | ||
| 1253 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PLLBW); | ||
| 1254 | hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN); | ||
| 1255 | hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN); | ||
| 1256 | hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR); | ||
| 1257 | hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET); | ||
| 1258 | hdmi_htop1_write(hdmi, 0x00000016, HDMI_HTOP1_CISRANGE); | ||
| 1259 | msleep(100); | ||
| 1260 | hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_ENABLE_SELECTOR); | ||
| 1261 | msleep(100); | ||
| 1262 | hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR); | ||
| 1263 | hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET); | ||
| 1264 | hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN); | ||
| 1265 | hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN); | ||
| 1266 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT); | ||
| 1267 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_CLK_TO_PHY); | ||
| 1268 | hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT2); | ||
| 1269 | hdmi_htop1_write(hdmi, 0x0000000a, HDMI_HTOP1_CLK_SET); | ||
| 1270 | } | ||
| 1271 | |||
| 1113 | static int __init sh_hdmi_probe(struct platform_device *pdev) | 1272 | static int __init sh_hdmi_probe(struct platform_device *pdev) |
| 1114 | { | 1273 | { |
| 1115 | struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; | 1274 | struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; |
| 1116 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1275 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1276 | struct resource *htop1_res; | ||
| 1117 | int irq = platform_get_irq(pdev, 0), ret; | 1277 | int irq = platform_get_irq(pdev, 0), ret; |
| 1118 | struct sh_hdmi *hdmi; | 1278 | struct sh_hdmi *hdmi; |
| 1119 | long rate; | 1279 | long rate; |
| @@ -1121,6 +1281,15 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
| 1121 | if (!res || !pdata || irq < 0) | 1281 | if (!res || !pdata || irq < 0) |
| 1122 | return -ENODEV; | 1282 | return -ENODEV; |
| 1123 | 1283 | ||
| 1284 | htop1_res = NULL; | ||
| 1285 | if (pdata->flags & HDMI_HAS_HTOP1) { | ||
| 1286 | htop1_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 1287 | if (!htop1_res) { | ||
| 1288 | dev_err(&pdev->dev, "htop1 needs register base\n"); | ||
| 1289 | return -EINVAL; | ||
| 1290 | } | ||
| 1291 | } | ||
| 1292 | |||
| 1124 | hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL); | 1293 | hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL); |
| 1125 | if (!hdmi) { | 1294 | if (!hdmi) { |
| 1126 | dev_err(&pdev->dev, "Cannot allocate device data\n"); | 1295 | dev_err(&pdev->dev, "Cannot allocate device data\n"); |
| @@ -1138,6 +1307,15 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
| 1138 | goto egetclk; | 1307 | goto egetclk; |
| 1139 | } | 1308 | } |
| 1140 | 1309 | ||
| 1310 | /* select register access functions */ | ||
| 1311 | if (pdata->flags & HDMI_32BIT_REG) { | ||
| 1312 | hdmi->write = __hdmi_write32; | ||
| 1313 | hdmi->read = __hdmi_read32; | ||
| 1314 | } else { | ||
| 1315 | hdmi->write = __hdmi_write8; | ||
| 1316 | hdmi->read = __hdmi_read8; | ||
| 1317 | } | ||
| 1318 | |||
| 1141 | /* An arbitrary relaxed pixclock just to get things started: from standard 480p */ | 1319 | /* An arbitrary relaxed pixclock just to get things started: from standard 480p */ |
| 1142 | rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037)); | 1320 | rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037)); |
| 1143 | if (rate > 0) | 1321 | if (rate > 0) |
| @@ -1176,6 +1354,24 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
| 1176 | pm_runtime_enable(&pdev->dev); | 1354 | pm_runtime_enable(&pdev->dev); |
| 1177 | pm_runtime_get_sync(&pdev->dev); | 1355 | pm_runtime_get_sync(&pdev->dev); |
| 1178 | 1356 | ||
| 1357 | /* init interrupt polarity */ | ||
| 1358 | if (pdata->flags & HDMI_OUTPUT_PUSH_PULL) | ||
| 1359 | hdmi_bit_set(hdmi, 0x02, 0x02, HDMI_SYSTEM_CTRL); | ||
| 1360 | |||
| 1361 | if (pdata->flags & HDMI_OUTPUT_POLARITY_HI) | ||
| 1362 | hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL); | ||
| 1363 | |||
| 1364 | /* enable htop1 register if needed */ | ||
| 1365 | if (htop1_res) { | ||
| 1366 | hdmi->htop1 = ioremap(htop1_res->start, resource_size(htop1_res)); | ||
| 1367 | if (!hdmi->htop1) { | ||
| 1368 | dev_err(&pdev->dev, "control register region already claimed\n"); | ||
| 1369 | ret = -ENOMEM; | ||
| 1370 | goto emap_htop1; | ||
| 1371 | } | ||
| 1372 | sh_hdmi_htop1_init(hdmi); | ||
| 1373 | } | ||
| 1374 | |||
| 1179 | /* Product and revision IDs are 0 in sh-mobile version */ | 1375 | /* Product and revision IDs are 0 in sh-mobile version */ |
| 1180 | dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", | 1376 | dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", |
| 1181 | hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); | 1377 | hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); |
| @@ -1199,6 +1395,9 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
| 1199 | ecodec: | 1395 | ecodec: |
| 1200 | free_irq(irq, hdmi); | 1396 | free_irq(irq, hdmi); |
| 1201 | ereqirq: | 1397 | ereqirq: |
| 1398 | if (hdmi->htop1) | ||
| 1399 | iounmap(hdmi->htop1); | ||
| 1400 | emap_htop1: | ||
| 1202 | pm_runtime_put(&pdev->dev); | 1401 | pm_runtime_put(&pdev->dev); |
| 1203 | pm_runtime_disable(&pdev->dev); | 1402 | pm_runtime_disable(&pdev->dev); |
| 1204 | iounmap(hdmi->base); | 1403 | iounmap(hdmi->base); |
| @@ -1230,6 +1429,8 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev) | |||
| 1230 | pm_runtime_disable(&pdev->dev); | 1429 | pm_runtime_disable(&pdev->dev); |
| 1231 | clk_disable(hdmi->hdmi_clk); | 1430 | clk_disable(hdmi->hdmi_clk); |
| 1232 | clk_put(hdmi->hdmi_clk); | 1431 | clk_put(hdmi->hdmi_clk); |
| 1432 | if (hdmi->htop1) | ||
| 1433 | iounmap(hdmi->htop1); | ||
| 1233 | iounmap(hdmi->base); | 1434 | iounmap(hdmi->base); |
| 1234 | release_mem_region(res->start, resource_size(res)); | 1435 | release_mem_region(res->start, resource_size(res)); |
| 1235 | kfree(hdmi); | 1436 | kfree(hdmi); |
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h index aff73842d877..85d6738b6c64 100644 --- a/drivers/video/sis/init.h +++ b/drivers/video/sis/init.h | |||
| @@ -105,51 +105,6 @@ static const unsigned short ModeIndex_1920x1440[] = {0x68, 0x69, 0x00, 0x6b}; | |||
| 105 | static const unsigned short ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00}; | 105 | static const unsigned short ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00}; |
| 106 | static const unsigned short ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e}; | 106 | static const unsigned short ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e}; |
| 107 | 107 | ||
| 108 | static const unsigned short SiS_DRAMType[17][5]={ | ||
| 109 | {0x0C,0x0A,0x02,0x40,0x39}, | ||
| 110 | {0x0D,0x0A,0x01,0x40,0x48}, | ||
| 111 | {0x0C,0x09,0x02,0x20,0x35}, | ||
| 112 | {0x0D,0x09,0x01,0x20,0x44}, | ||
| 113 | {0x0C,0x08,0x02,0x10,0x31}, | ||
| 114 | {0x0D,0x08,0x01,0x10,0x40}, | ||
| 115 | {0x0C,0x0A,0x01,0x20,0x34}, | ||
| 116 | {0x0C,0x09,0x01,0x08,0x32}, | ||
| 117 | {0x0B,0x08,0x02,0x08,0x21}, | ||
| 118 | {0x0C,0x08,0x01,0x08,0x30}, | ||
| 119 | {0x0A,0x08,0x02,0x04,0x11}, | ||
| 120 | {0x0B,0x0A,0x01,0x10,0x28}, | ||
| 121 | {0x09,0x08,0x02,0x02,0x01}, | ||
| 122 | {0x0B,0x09,0x01,0x08,0x24}, | ||
| 123 | {0x0B,0x08,0x01,0x04,0x20}, | ||
| 124 | {0x0A,0x08,0x01,0x02,0x10}, | ||
| 125 | {0x09,0x08,0x01,0x01,0x00} | ||
| 126 | }; | ||
| 127 | |||
| 128 | static const unsigned short SiS_SDRDRAM_TYPE[13][5] = | ||
| 129 | { | ||
| 130 | { 2,12, 9,64,0x35}, | ||
| 131 | { 1,13, 9,64,0x44}, | ||
| 132 | { 2,12, 8,32,0x31}, | ||
| 133 | { 2,11, 9,32,0x25}, | ||
| 134 | { 1,12, 9,32,0x34}, | ||
| 135 | { 1,13, 8,32,0x40}, | ||
| 136 | { 2,11, 8,16,0x21}, | ||
| 137 | { 1,12, 8,16,0x30}, | ||
| 138 | { 1,11, 9,16,0x24}, | ||
| 139 | { 1,11, 8, 8,0x20}, | ||
| 140 | { 2, 9, 8, 4,0x01}, | ||
| 141 | { 1,10, 8, 4,0x10}, | ||
| 142 | { 1, 9, 8, 2,0x00} | ||
| 143 | }; | ||
| 144 | |||
| 145 | static const unsigned short SiS_DDRDRAM_TYPE[4][5] = | ||
| 146 | { | ||
| 147 | { 2,12, 9,64,0x35}, | ||
| 148 | { 2,12, 8,32,0x31}, | ||
| 149 | { 2,11, 8,16,0x21}, | ||
| 150 | { 2, 9, 8, 4,0x01} | ||
| 151 | }; | ||
| 152 | |||
| 153 | static const unsigned char SiS_MDA_DAC[] = | 108 | static const unsigned char SiS_MDA_DAC[] = |
| 154 | { | 109 | { |
| 155 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | 110 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 078ca2167d6f..a7a48db64ce2 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
| @@ -4222,6 +4222,26 @@ sisfb_post_300_buswidth(struct sis_video_info *ivideo) | |||
| 4222 | return 1; /* 32bit */ | 4222 | return 1; /* 32bit */ |
| 4223 | } | 4223 | } |
| 4224 | 4224 | ||
| 4225 | static const unsigned short __devinitconst SiS_DRAMType[17][5] = { | ||
| 4226 | {0x0C,0x0A,0x02,0x40,0x39}, | ||
| 4227 | {0x0D,0x0A,0x01,0x40,0x48}, | ||
| 4228 | {0x0C,0x09,0x02,0x20,0x35}, | ||
| 4229 | {0x0D,0x09,0x01,0x20,0x44}, | ||
| 4230 | {0x0C,0x08,0x02,0x10,0x31}, | ||
| 4231 | {0x0D,0x08,0x01,0x10,0x40}, | ||
| 4232 | {0x0C,0x0A,0x01,0x20,0x34}, | ||
| 4233 | {0x0C,0x09,0x01,0x08,0x32}, | ||
| 4234 | {0x0B,0x08,0x02,0x08,0x21}, | ||
| 4235 | {0x0C,0x08,0x01,0x08,0x30}, | ||
| 4236 | {0x0A,0x08,0x02,0x04,0x11}, | ||
| 4237 | {0x0B,0x0A,0x01,0x10,0x28}, | ||
| 4238 | {0x09,0x08,0x02,0x02,0x01}, | ||
| 4239 | {0x0B,0x09,0x01,0x08,0x24}, | ||
| 4240 | {0x0B,0x08,0x01,0x04,0x20}, | ||
| 4241 | {0x0A,0x08,0x01,0x02,0x10}, | ||
| 4242 | {0x09,0x08,0x01,0x01,0x00} | ||
| 4243 | }; | ||
| 4244 | |||
| 4225 | static int __devinit | 4245 | static int __devinit |
| 4226 | sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth, | 4246 | sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth, |
| 4227 | int PseudoRankCapacity, int PseudoAdrPinCount, | 4247 | int PseudoRankCapacity, int PseudoAdrPinCount, |
| @@ -4231,27 +4251,8 @@ sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth | |||
| 4231 | unsigned short sr14; | 4251 | unsigned short sr14; |
| 4232 | unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid; | 4252 | unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid; |
| 4233 | unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage; | 4253 | unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage; |
| 4234 | static const unsigned short SiS_DRAMType[17][5] = { | ||
| 4235 | {0x0C,0x0A,0x02,0x40,0x39}, | ||
| 4236 | {0x0D,0x0A,0x01,0x40,0x48}, | ||
| 4237 | {0x0C,0x09,0x02,0x20,0x35}, | ||
| 4238 | {0x0D,0x09,0x01,0x20,0x44}, | ||
| 4239 | {0x0C,0x08,0x02,0x10,0x31}, | ||
| 4240 | {0x0D,0x08,0x01,0x10,0x40}, | ||
| 4241 | {0x0C,0x0A,0x01,0x20,0x34}, | ||
| 4242 | {0x0C,0x09,0x01,0x08,0x32}, | ||
| 4243 | {0x0B,0x08,0x02,0x08,0x21}, | ||
| 4244 | {0x0C,0x08,0x01,0x08,0x30}, | ||
| 4245 | {0x0A,0x08,0x02,0x04,0x11}, | ||
| 4246 | {0x0B,0x0A,0x01,0x10,0x28}, | ||
| 4247 | {0x09,0x08,0x02,0x02,0x01}, | ||
| 4248 | {0x0B,0x09,0x01,0x08,0x24}, | ||
| 4249 | {0x0B,0x08,0x01,0x04,0x20}, | ||
| 4250 | {0x0A,0x08,0x01,0x02,0x10}, | ||
| 4251 | {0x09,0x08,0x01,0x01,0x00} | ||
| 4252 | }; | ||
| 4253 | 4254 | ||
| 4254 | for(k = 0; k <= 16; k++) { | 4255 | for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) { |
| 4255 | 4256 | ||
| 4256 | RankCapacity = buswidth * SiS_DRAMType[k][3]; | 4257 | RankCapacity = buswidth * SiS_DRAMType[k][3]; |
| 4257 | 4258 | ||
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 30f7a815a62b..5b6abc6de84b 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c | |||
| @@ -1036,6 +1036,6 @@ static void __exit xxxfb_exit(void) | |||
| 1036 | */ | 1036 | */ |
| 1037 | 1037 | ||
| 1038 | module_init(xxxfb_init); | 1038 | module_init(xxxfb_init); |
| 1039 | module_exit(xxxfb_remove); | 1039 | module_exit(xxxfb_exit); |
| 1040 | 1040 | ||
| 1041 | MODULE_LICENSE("GPL"); | 1041 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c index ccbfef5e828f..af3ef27ad36c 100644 --- a/drivers/video/smscufx.c +++ b/drivers/video/smscufx.c | |||
| @@ -846,7 +846,7 @@ static void ufx_raw_rect(struct ufx_data *dev, u16 *cmd, int x, int y, | |||
| 846 | } | 846 | } |
| 847 | } | 847 | } |
| 848 | 848 | ||
| 849 | int ufx_handle_damage(struct ufx_data *dev, int x, int y, | 849 | static int ufx_handle_damage(struct ufx_data *dev, int x, int y, |
| 850 | int width, int height) | 850 | int width, int height) |
| 851 | { | 851 | { |
| 852 | size_t packed_line_len = ALIGN((width * 2), 4); | 852 | size_t packed_line_len = ALIGN((width * 2), 4); |
| @@ -1083,7 +1083,7 @@ static int ufx_ops_open(struct fb_info *info, int user) | |||
| 1083 | 1083 | ||
| 1084 | struct fb_deferred_io *fbdefio; | 1084 | struct fb_deferred_io *fbdefio; |
| 1085 | 1085 | ||
| 1086 | fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); | 1086 | fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); |
| 1087 | 1087 | ||
| 1088 | if (fbdefio) { | 1088 | if (fbdefio) { |
| 1089 | fbdefio->delay = UFX_DEFIO_WRITE_DELAY; | 1089 | fbdefio->delay = UFX_DEFIO_WRITE_DELAY; |
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index 7af1e8166182..8af64148294b 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c | |||
| @@ -893,7 +893,7 @@ static int dlfb_ops_open(struct fb_info *info, int user) | |||
| 893 | 893 | ||
| 894 | struct fb_deferred_io *fbdefio; | 894 | struct fb_deferred_io *fbdefio; |
| 895 | 895 | ||
| 896 | fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); | 896 | fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); |
| 897 | 897 | ||
| 898 | if (fbdefio) { | 898 | if (fbdefio) { |
| 899 | fbdefio->delay = DL_DEFIO_WRITE_DELAY; | 899 | fbdefio->delay = DL_DEFIO_WRITE_DELAY; |
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 0c8837565bc7..c80e770e1800 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
| @@ -1276,17 +1276,12 @@ static int viafb_dfph_proc_open(struct inode *inode, struct file *file) | |||
| 1276 | static ssize_t viafb_dfph_proc_write(struct file *file, | 1276 | static ssize_t viafb_dfph_proc_write(struct file *file, |
| 1277 | const char __user *buffer, size_t count, loff_t *pos) | 1277 | const char __user *buffer, size_t count, loff_t *pos) |
| 1278 | { | 1278 | { |
| 1279 | char buf[20]; | 1279 | int err; |
| 1280 | u8 reg_val = 0; | 1280 | u8 reg_val; |
| 1281 | unsigned long length; | 1281 | err = kstrtou8_from_user(buffer, count, 0, ®_val); |
| 1282 | if (count < 1) | 1282 | if (err) |
| 1283 | return -EINVAL; | 1283 | return err; |
| 1284 | length = count > 20 ? 20 : count; | 1284 | |
| 1285 | if (copy_from_user(&buf[0], buffer, length)) | ||
| 1286 | return -EFAULT; | ||
| 1287 | buf[length - 1] = '\0'; /*Ensure end string */ | ||
| 1288 | if (kstrtou8(buf, 0, ®_val) < 0) | ||
| 1289 | return -EINVAL; | ||
| 1290 | viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f); | 1285 | viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f); |
| 1291 | return count; | 1286 | return count; |
| 1292 | } | 1287 | } |
| @@ -1316,17 +1311,12 @@ static int viafb_dfpl_proc_open(struct inode *inode, struct file *file) | |||
| 1316 | static ssize_t viafb_dfpl_proc_write(struct file *file, | 1311 | static ssize_t viafb_dfpl_proc_write(struct file *file, |
| 1317 | const char __user *buffer, size_t count, loff_t *pos) | 1312 | const char __user *buffer, size_t count, loff_t *pos) |
| 1318 | { | 1313 | { |
| 1319 | char buf[20]; | 1314 | int err; |
| 1320 | u8 reg_val = 0; | 1315 | u8 reg_val; |
| 1321 | unsigned long length; | 1316 | err = kstrtou8_from_user(buffer, count, 0, ®_val); |
| 1322 | if (count < 1) | 1317 | if (err) |
| 1323 | return -EINVAL; | 1318 | return err; |
| 1324 | length = count > 20 ? 20 : count; | 1319 | |
| 1325 | if (copy_from_user(&buf[0], buffer, length)) | ||
| 1326 | return -EFAULT; | ||
| 1327 | buf[length - 1] = '\0'; /*Ensure end string */ | ||
| 1328 | if (kstrtou8(buf, 0, ®_val) < 0) | ||
| 1329 | return -EINVAL; | ||
| 1330 | viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f); | 1320 | viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f); |
| 1331 | return count; | 1321 | return count; |
| 1332 | } | 1322 | } |
diff --git a/include/linux/fb.h b/include/linux/fb.h index a3229d7ab9f2..ac3f1c605843 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
| @@ -611,6 +611,7 @@ struct fb_deferred_io { | |||
| 611 | struct mutex lock; /* mutex that protects the page list */ | 611 | struct mutex lock; /* mutex that protects the page list */ |
| 612 | struct list_head pagelist; /* list of touched pages */ | 612 | struct list_head pagelist; /* list of touched pages */ |
| 613 | /* callback */ | 613 | /* callback */ |
| 614 | void (*first_io)(struct fb_info *info); | ||
| 614 | void (*deferred_io)(struct fb_info *info, struct list_head *pagelist); | 615 | void (*deferred_io)(struct fb_info *info, struct list_head *pagelist); |
| 615 | }; | 616 | }; |
| 616 | #endif | 617 | #endif |
diff --git a/include/video/auo_k190xfb.h b/include/video/auo_k190xfb.h new file mode 100644 index 000000000000..609efe8c686e --- /dev/null +++ b/include/video/auo_k190xfb.h | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | /* | ||
| 2 | * Definitions for AUO-K190X framebuffer drivers | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef _LINUX_VIDEO_AUO_K190XFB_H_ | ||
| 12 | #define _LINUX_VIDEO_AUO_K190XFB_H_ | ||
| 13 | |||
| 14 | /* Controller standby command needs a param */ | ||
| 15 | #define AUOK190X_QUIRK_STANDBYPARAM (1 << 0) | ||
| 16 | |||
| 17 | /* Controller standby is completely broken */ | ||
| 18 | #define AUOK190X_QUIRK_STANDBYBROKEN (1 << 1) | ||
| 19 | |||
| 20 | /* | ||
| 21 | * Resolutions for the displays | ||
| 22 | */ | ||
| 23 | #define AUOK190X_RESOLUTION_800_600 0 | ||
| 24 | #define AUOK190X_RESOLUTION_1024_768 1 | ||
| 25 | |||
| 26 | /* | ||
| 27 | * struct used by auok190x. board specific stuff comes from *board | ||
| 28 | */ | ||
| 29 | struct auok190xfb_par { | ||
| 30 | struct fb_info *info; | ||
| 31 | struct auok190x_board *board; | ||
| 32 | |||
| 33 | struct regulator *regulator; | ||
| 34 | |||
| 35 | struct mutex io_lock; | ||
| 36 | struct delayed_work work; | ||
| 37 | wait_queue_head_t waitq; | ||
| 38 | int resolution; | ||
| 39 | int rotation; | ||
| 40 | int consecutive_threshold; | ||
| 41 | int update_cnt; | ||
| 42 | |||
| 43 | /* panel and controller informations */ | ||
| 44 | int epd_type; | ||
| 45 | int panel_size_int; | ||
| 46 | int panel_size_float; | ||
| 47 | int panel_model; | ||
| 48 | int tcon_version; | ||
| 49 | int lut_version; | ||
| 50 | |||
| 51 | /* individual controller callbacks */ | ||
| 52 | void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2); | ||
| 53 | void (*update_all)(struct auok190xfb_par *par); | ||
| 54 | bool (*need_refresh)(struct auok190xfb_par *par); | ||
| 55 | void (*init)(struct auok190xfb_par *par); | ||
| 56 | void (*recover)(struct auok190xfb_par *par); | ||
| 57 | |||
| 58 | int update_mode; /* mode to use for updates */ | ||
| 59 | int last_mode; /* update mode last used */ | ||
| 60 | int flash; | ||
| 61 | |||
| 62 | /* power management */ | ||
| 63 | int autosuspend_delay; | ||
| 64 | bool standby; | ||
| 65 | bool manual_standby; | ||
| 66 | }; | ||
| 67 | |||
| 68 | /** | ||
| 69 | * Board specific platform-data | ||
| 70 | * @init: initialize the controller interface | ||
| 71 | * @cleanup: cleanup the controller interface | ||
| 72 | * @wait_for_rdy: wait until the controller is not busy anymore | ||
| 73 | * @set_ctl: change an interface control | ||
| 74 | * @set_hdb: write a value to the data register | ||
| 75 | * @get_hdb: read a value from the data register | ||
| 76 | * @setup_irq: method to setup the irq handling on the busy gpio | ||
| 77 | * @gpio_nsleep: sleep gpio | ||
| 78 | * @gpio_nrst: reset gpio | ||
| 79 | * @gpio_nbusy: busy gpio | ||
| 80 | * @resolution: one of the AUOK190X_RESOLUTION constants | ||
| 81 | * @rotation: rotation of the framebuffer | ||
| 82 | * @quirks: controller quirks to honor | ||
| 83 | * @fps: frames per second for defio | ||
| 84 | */ | ||
| 85 | struct auok190x_board { | ||
| 86 | int (*init)(struct auok190xfb_par *); | ||
| 87 | void (*cleanup)(struct auok190xfb_par *); | ||
| 88 | int (*wait_for_rdy)(struct auok190xfb_par *); | ||
| 89 | |||
| 90 | void (*set_ctl)(struct auok190xfb_par *, unsigned char, u8); | ||
| 91 | void (*set_hdb)(struct auok190xfb_par *, u16); | ||
| 92 | u16 (*get_hdb)(struct auok190xfb_par *); | ||
| 93 | |||
| 94 | int (*setup_irq)(struct fb_info *); | ||
| 95 | |||
| 96 | int gpio_nsleep; | ||
| 97 | int gpio_nrst; | ||
| 98 | int gpio_nbusy; | ||
| 99 | |||
| 100 | int resolution; | ||
| 101 | int rotation; | ||
| 102 | int quirks; | ||
| 103 | int fps; | ||
| 104 | }; | ||
| 105 | |||
| 106 | #endif | ||
diff --git a/include/video/exynos_dp.h b/include/video/exynos_dp.h index 8847a9d6dd42..bd8cabd344db 100644 --- a/include/video/exynos_dp.h +++ b/include/video/exynos_dp.h | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | #define DP_TIMEOUT_LOOP_COUNT 100 | 15 | #define DP_TIMEOUT_LOOP_COUNT 100 |
| 16 | #define MAX_CR_LOOP 5 | 16 | #define MAX_CR_LOOP 5 |
| 17 | #define MAX_EQ_LOOP 4 | 17 | #define MAX_EQ_LOOP 5 |
| 18 | 18 | ||
| 19 | enum link_rate_type { | 19 | enum link_rate_type { |
| 20 | LINK_RATE_1_62GBPS = 0x06, | 20 | LINK_RATE_1_62GBPS = 0x06, |
diff --git a/include/video/exynos_mipi_dsim.h b/include/video/exynos_mipi_dsim.h index 772c770535f1..83ce5e667d47 100644 --- a/include/video/exynos_mipi_dsim.h +++ b/include/video/exynos_mipi_dsim.h | |||
| @@ -315,6 +315,7 @@ struct mipi_dsim_lcd_device { | |||
| 315 | int id; | 315 | int id; |
| 316 | int bus_id; | 316 | int bus_id; |
| 317 | int irq; | 317 | int irq; |
| 318 | int panel_reverse; | ||
| 318 | 319 | ||
| 319 | struct mipi_dsim_device *master; | 320 | struct mipi_dsim_device *master; |
| 320 | void *platform_data; | 321 | void *platform_data; |
diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 1c46a14341dd..c8e59b4a3364 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h | |||
| @@ -51,6 +51,8 @@ | |||
| 51 | 51 | ||
| 52 | struct omap_dss_device; | 52 | struct omap_dss_device; |
| 53 | struct omap_overlay_manager; | 53 | struct omap_overlay_manager; |
| 54 | struct snd_aes_iec958; | ||
| 55 | struct snd_cea_861_aud_if; | ||
| 54 | 56 | ||
| 55 | enum omap_display_type { | 57 | enum omap_display_type { |
| 56 | OMAP_DISPLAY_TYPE_NONE = 0, | 58 | OMAP_DISPLAY_TYPE_NONE = 0, |
| @@ -158,6 +160,13 @@ enum omap_dss_display_state { | |||
| 158 | OMAP_DSS_DISPLAY_SUSPENDED, | 160 | OMAP_DSS_DISPLAY_SUSPENDED, |
| 159 | }; | 161 | }; |
| 160 | 162 | ||
| 163 | enum omap_dss_audio_state { | ||
| 164 | OMAP_DSS_AUDIO_DISABLED = 0, | ||
| 165 | OMAP_DSS_AUDIO_ENABLED, | ||
| 166 | OMAP_DSS_AUDIO_CONFIGURED, | ||
| 167 | OMAP_DSS_AUDIO_PLAYING, | ||
| 168 | }; | ||
| 169 | |||
| 161 | /* XXX perhaps this should be removed */ | 170 | /* XXX perhaps this should be removed */ |
| 162 | enum omap_dss_overlay_managers { | 171 | enum omap_dss_overlay_managers { |
| 163 | OMAP_DSS_OVL_MGR_LCD, | 172 | OMAP_DSS_OVL_MGR_LCD, |
| @@ -166,8 +175,9 @@ enum omap_dss_overlay_managers { | |||
| 166 | }; | 175 | }; |
| 167 | 176 | ||
| 168 | enum omap_dss_rotation_type { | 177 | enum omap_dss_rotation_type { |
| 169 | OMAP_DSS_ROT_DMA = 0, | 178 | OMAP_DSS_ROT_DMA = 1 << 0, |
| 170 | OMAP_DSS_ROT_VRFB = 1, | 179 | OMAP_DSS_ROT_VRFB = 1 << 1, |
| 180 | OMAP_DSS_ROT_TILER = 1 << 2, | ||
| 171 | }; | 181 | }; |
| 172 | 182 | ||
| 173 | /* clockwise rotation angle */ | 183 | /* clockwise rotation angle */ |
| @@ -309,6 +319,7 @@ struct omap_dss_board_info { | |||
| 309 | struct omap_dss_device *default_device; | 319 | struct omap_dss_device *default_device; |
| 310 | int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask); | 320 | int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask); |
| 311 | void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask); | 321 | void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask); |
| 322 | int (*set_min_bus_tput)(struct device *dev, unsigned long r); | ||
| 312 | }; | 323 | }; |
| 313 | 324 | ||
| 314 | /* Init with the board info */ | 325 | /* Init with the board info */ |
| @@ -316,11 +327,6 @@ extern int omap_display_init(struct omap_dss_board_info *board_data); | |||
| 316 | /* HDMI mux init*/ | 327 | /* HDMI mux init*/ |
| 317 | extern int omap_hdmi_init(enum omap_hdmi_flags flags); | 328 | extern int omap_hdmi_init(enum omap_hdmi_flags flags); |
| 318 | 329 | ||
| 319 | struct omap_display_platform_data { | ||
| 320 | struct omap_dss_board_info *board_data; | ||
| 321 | /* TODO: Additional members to be added when PM is considered */ | ||
| 322 | }; | ||
| 323 | |||
| 324 | struct omap_video_timings { | 330 | struct omap_video_timings { |
| 325 | /* Unit: pixels */ | 331 | /* Unit: pixels */ |
| 326 | u16 x_res; | 332 | u16 x_res; |
| @@ -587,6 +593,8 @@ struct omap_dss_device { | |||
| 587 | 593 | ||
| 588 | enum omap_dss_display_state state; | 594 | enum omap_dss_display_state state; |
| 589 | 595 | ||
| 596 | enum omap_dss_audio_state audio_state; | ||
| 597 | |||
| 590 | /* platform specific */ | 598 | /* platform specific */ |
| 591 | int (*platform_enable)(struct omap_dss_device *dssdev); | 599 | int (*platform_enable)(struct omap_dss_device *dssdev); |
| 592 | void (*platform_disable)(struct omap_dss_device *dssdev); | 600 | void (*platform_disable)(struct omap_dss_device *dssdev); |
| @@ -599,6 +607,11 @@ struct omap_dss_hdmi_data | |||
| 599 | int hpd_gpio; | 607 | int hpd_gpio; |
| 600 | }; | 608 | }; |
| 601 | 609 | ||
| 610 | struct omap_dss_audio { | ||
| 611 | struct snd_aes_iec958 *iec; | ||
| 612 | struct snd_cea_861_aud_if *cea; | ||
| 613 | }; | ||
| 614 | |||
| 602 | struct omap_dss_driver { | 615 | struct omap_dss_driver { |
| 603 | struct device_driver driver; | 616 | struct device_driver driver; |
| 604 | 617 | ||
| @@ -646,6 +659,24 @@ struct omap_dss_driver { | |||
| 646 | 659 | ||
| 647 | int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); | 660 | int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); |
| 648 | bool (*detect)(struct omap_dss_device *dssdev); | 661 | bool (*detect)(struct omap_dss_device *dssdev); |
| 662 | |||
| 663 | /* | ||
| 664 | * For display drivers that support audio. This encompasses | ||
| 665 | * HDMI and DisplayPort at the moment. | ||
| 666 | */ | ||
| 667 | /* | ||
| 668 | * Note: These functions might sleep. Do not call while | ||
| 669 | * holding a spinlock/readlock. | ||
| 670 | */ | ||
| 671 | int (*audio_enable)(struct omap_dss_device *dssdev); | ||
| 672 | void (*audio_disable)(struct omap_dss_device *dssdev); | ||
| 673 | bool (*audio_supported)(struct omap_dss_device *dssdev); | ||
| 674 | int (*audio_config)(struct omap_dss_device *dssdev, | ||
| 675 | struct omap_dss_audio *audio); | ||
| 676 | /* Note: These functions may not sleep */ | ||
| 677 | int (*audio_start)(struct omap_dss_device *dssdev); | ||
| 678 | void (*audio_stop)(struct omap_dss_device *dssdev); | ||
| 679 | |||
| 649 | }; | 680 | }; |
| 650 | 681 | ||
| 651 | int omap_dss_register_driver(struct omap_dss_driver *); | 682 | int omap_dss_register_driver(struct omap_dss_driver *); |
| @@ -670,6 +701,8 @@ struct omap_overlay *omap_dss_get_overlay(int num); | |||
| 670 | void omapdss_default_get_resolution(struct omap_dss_device *dssdev, | 701 | void omapdss_default_get_resolution(struct omap_dss_device *dssdev, |
| 671 | u16 *xres, u16 *yres); | 702 | u16 *xres, u16 *yres); |
| 672 | int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev); | 703 | int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev); |
| 704 | void omapdss_default_get_timings(struct omap_dss_device *dssdev, | ||
| 705 | struct omap_video_timings *timings); | ||
| 673 | 706 | ||
| 674 | typedef void (*omap_dispc_isr_t) (void *arg, u32 mask); | 707 | typedef void (*omap_dispc_isr_t) (void *arg, u32 mask); |
| 675 | int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); | 708 | int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); |
diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h index 728f9de9c258..63d20efa254a 100644 --- a/include/video/sh_mobile_hdmi.h +++ b/include/video/sh_mobile_hdmi.h | |||
| @@ -18,9 +18,11 @@ struct clk; | |||
| 18 | /* | 18 | /* |
| 19 | * flags format | 19 | * flags format |
| 20 | * | 20 | * |
| 21 | * 0x0000000A | 21 | * 0x00000CBA |
| 22 | * | 22 | * |
| 23 | * A: Audio source select | 23 | * A: Audio source select |
| 24 | * B: Int output option | ||
| 25 | * C: Chip specific option | ||
| 24 | */ | 26 | */ |
| 25 | 27 | ||
| 26 | /* Audio source select */ | 28 | /* Audio source select */ |
| @@ -30,6 +32,14 @@ struct clk; | |||
| 30 | #define HDMI_SND_SRC_DSD (2 << 0) | 32 | #define HDMI_SND_SRC_DSD (2 << 0) |
| 31 | #define HDMI_SND_SRC_HBR (3 << 0) | 33 | #define HDMI_SND_SRC_HBR (3 << 0) |
| 32 | 34 | ||
| 35 | /* Int output option */ | ||
| 36 | #define HDMI_OUTPUT_PUSH_PULL (1 << 4) /* System control : output mode */ | ||
| 37 | #define HDMI_OUTPUT_POLARITY_HI (1 << 5) /* System control : output polarity */ | ||
| 38 | |||
| 39 | /* Chip specific option */ | ||
| 40 | #define HDMI_32BIT_REG (1 << 8) | ||
| 41 | #define HDMI_HAS_HTOP1 (1 << 9) | ||
| 42 | |||
| 33 | struct sh_mobile_hdmi_info { | 43 | struct sh_mobile_hdmi_info { |
| 34 | unsigned int flags; | 44 | unsigned int flags; |
| 35 | long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq, | 45 | long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq, |
