diff options
author | Dave Airlie <airlied@redhat.com> | 2015-06-11 20:14:00 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-06-11 20:14:00 -0400 |
commit | 7207d559e4851372c00344fa52778d73a0098627 (patch) | |
tree | 72cce8655a862a82d3759af3188bbdebc500e6af | |
parent | 3f05eb4e3fc56df678f83925ced78bc97166b052 (diff) | |
parent | c58d6d1b6652b0a8db4aef7e93fb21ee869b5387 (diff) |
Merge branch '2015-06-08-st-drm-next' of http://git.linaro.org/people/benjamin.gaignard/kernel into drm-next
Mainly it is fixing timing on HDMI to be compliant with CEA-861E spec.
* '2015-06-08-st-drm-next' of http://git.linaro.org/people/benjamin.gaignard/kernel:
drm/sti: vtg fix CEA-861E video format timing error
drm/sti: hdmi fix CEA-861E video format timing error
drm/sti: VTG interrupt names are badly displayed
drm/sti: missing first pixel column on HDMI display
drm/sti: correctly test devm_ioremap() return
-rw-r--r-- | drivers/gpu/drm/sti/sti_dvo.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_hdmi.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_vtg.c | 56 |
3 files changed, 43 insertions, 21 deletions
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index a9b678af85a6..d141d645bd13 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c | |||
@@ -499,8 +499,8 @@ static int sti_dvo_probe(struct platform_device *pdev) | |||
499 | } | 499 | } |
500 | dvo->regs = devm_ioremap_nocache(dev, res->start, | 500 | dvo->regs = devm_ioremap_nocache(dev, res->start, |
501 | resource_size(res)); | 501 | resource_size(res)); |
502 | if (IS_ERR(dvo->regs)) | 502 | if (!dvo->regs) |
503 | return PTR_ERR(dvo->regs); | 503 | return -ENOMEM; |
504 | 504 | ||
505 | dvo->clk_pix = devm_clk_get(dev, "dvo_pix"); | 505 | dvo->clk_pix = devm_clk_get(dev, "dvo_pix"); |
506 | if (IS_ERR(dvo->clk_pix)) { | 506 | if (IS_ERR(dvo->clk_pix)) { |
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index ae5424bd6b4c..f28a4d54487c 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c | |||
@@ -192,8 +192,8 @@ static void hdmi_active_area(struct sti_hdmi *hdmi) | |||
192 | u32 xmin, xmax; | 192 | u32 xmin, xmax; |
193 | u32 ymin, ymax; | 193 | u32 ymin, ymax; |
194 | 194 | ||
195 | xmin = sti_vtg_get_pixel_number(hdmi->mode, 0); | 195 | xmin = sti_vtg_get_pixel_number(hdmi->mode, 1); |
196 | xmax = sti_vtg_get_pixel_number(hdmi->mode, hdmi->mode.hdisplay - 1); | 196 | xmax = sti_vtg_get_pixel_number(hdmi->mode, hdmi->mode.hdisplay); |
197 | ymin = sti_vtg_get_line_number(hdmi->mode, 0); | 197 | ymin = sti_vtg_get_line_number(hdmi->mode, 0); |
198 | ymax = sti_vtg_get_line_number(hdmi->mode, hdmi->mode.vdisplay - 1); | 198 | ymax = sti_vtg_get_line_number(hdmi->mode, hdmi->mode.vdisplay - 1); |
199 | 199 | ||
diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c index 9564f2568e2c..aa8097137701 100644 --- a/drivers/gpu/drm/sti/sti_vtg.c +++ b/drivers/gpu/drm/sti/sti_vtg.c | |||
@@ -62,7 +62,7 @@ | |||
62 | #define VTG_IRQ_MASK (VTG_IRQ_TOP | VTG_IRQ_BOTTOM) | 62 | #define VTG_IRQ_MASK (VTG_IRQ_TOP | VTG_IRQ_BOTTOM) |
63 | 63 | ||
64 | /* Delay introduced by the HDMI in nb of pixel */ | 64 | /* Delay introduced by the HDMI in nb of pixel */ |
65 | #define HDMI_DELAY (6) | 65 | #define HDMI_DELAY (5) |
66 | 66 | ||
67 | /* delay introduced by the Arbitrary Waveform Generator in nb of pixels */ | 67 | /* delay introduced by the Arbitrary Waveform Generator in nb of pixels */ |
68 | #define AWG_DELAY_HD (-9) | 68 | #define AWG_DELAY_HD (-9) |
@@ -121,6 +121,32 @@ static void vtg_reset(struct sti_vtg *vtg) | |||
121 | writel(1, vtg->regs + VTG_DRST_AUTOC); | 121 | writel(1, vtg->regs + VTG_DRST_AUTOC); |
122 | } | 122 | } |
123 | 123 | ||
124 | static void vtg_set_output_window(void __iomem *regs, | ||
125 | const struct drm_display_mode *mode) | ||
126 | { | ||
127 | u32 video_top_field_start; | ||
128 | u32 video_top_field_stop; | ||
129 | u32 video_bottom_field_start; | ||
130 | u32 video_bottom_field_stop; | ||
131 | u32 xstart = sti_vtg_get_pixel_number(*mode, 0); | ||
132 | u32 ystart = sti_vtg_get_line_number(*mode, 0); | ||
133 | u32 xstop = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1); | ||
134 | u32 ystop = sti_vtg_get_line_number(*mode, mode->vdisplay - 1); | ||
135 | |||
136 | /* Set output window to fit the display mode selected */ | ||
137 | video_top_field_start = (ystart << 16) | xstart; | ||
138 | video_top_field_stop = (ystop << 16) | xstop; | ||
139 | |||
140 | /* Only progressive supported for now */ | ||
141 | video_bottom_field_start = video_top_field_start; | ||
142 | video_bottom_field_stop = video_top_field_stop; | ||
143 | |||
144 | writel(video_top_field_start, regs + VTG_VID_TFO); | ||
145 | writel(video_top_field_stop, regs + VTG_VID_TFS); | ||
146 | writel(video_bottom_field_start, regs + VTG_VID_BFO); | ||
147 | writel(video_bottom_field_stop, regs + VTG_VID_BFS); | ||
148 | } | ||
149 | |||
124 | static void vtg_set_mode(struct sti_vtg *vtg, | 150 | static void vtg_set_mode(struct sti_vtg *vtg, |
125 | int type, const struct drm_display_mode *mode) | 151 | int type, const struct drm_display_mode *mode) |
126 | { | 152 | { |
@@ -129,18 +155,14 @@ static void vtg_set_mode(struct sti_vtg *vtg, | |||
129 | if (vtg->slave) | 155 | if (vtg->slave) |
130 | vtg_set_mode(vtg->slave, VTG_TYPE_SLAVE_BY_EXT0, mode); | 156 | vtg_set_mode(vtg->slave, VTG_TYPE_SLAVE_BY_EXT0, mode); |
131 | 157 | ||
158 | /* Set the number of clock cycles per line */ | ||
132 | writel(mode->htotal, vtg->regs + VTG_CLKLN); | 159 | writel(mode->htotal, vtg->regs + VTG_CLKLN); |
133 | writel(mode->vtotal * 2, vtg->regs + VTG_HLFLN); | ||
134 | 160 | ||
135 | tmp = (mode->vtotal - mode->vsync_start + 1) << 16; | 161 | /* Set Half Line Per Field (only progressive supported for now) */ |
136 | tmp |= mode->htotal - mode->hsync_start; | 162 | writel(mode->vtotal * 2, vtg->regs + VTG_HLFLN); |
137 | writel(tmp, vtg->regs + VTG_VID_TFO); | ||
138 | writel(tmp, vtg->regs + VTG_VID_BFO); | ||
139 | 163 | ||
140 | tmp = (mode->vdisplay + mode->vtotal - mode->vsync_start + 1) << 16; | 164 | /* Program output window */ |
141 | tmp |= mode->hdisplay + mode->htotal - mode->hsync_start; | 165 | vtg_set_output_window(vtg->regs, mode); |
142 | writel(tmp, vtg->regs + VTG_VID_TFS); | ||
143 | writel(tmp, vtg->regs + VTG_VID_BFS); | ||
144 | 166 | ||
145 | /* prepare VTG set 1 for HDMI */ | 167 | /* prepare VTG set 1 for HDMI */ |
146 | tmp = (mode->hsync_end - mode->hsync_start + HDMI_DELAY) << 16; | 168 | tmp = (mode->hsync_end - mode->hsync_start + HDMI_DELAY) << 16; |
@@ -151,8 +173,11 @@ static void vtg_set_mode(struct sti_vtg *vtg, | |||
151 | tmp |= 1; | 173 | tmp |= 1; |
152 | writel(tmp, vtg->regs + VTG_TOP_V_VD_1); | 174 | writel(tmp, vtg->regs + VTG_TOP_V_VD_1); |
153 | writel(tmp, vtg->regs + VTG_BOT_V_VD_1); | 175 | writel(tmp, vtg->regs + VTG_BOT_V_VD_1); |
154 | writel(0, vtg->regs + VTG_TOP_V_HD_1); | 176 | |
155 | writel(0, vtg->regs + VTG_BOT_V_HD_1); | 177 | tmp = HDMI_DELAY << 16; |
178 | tmp |= HDMI_DELAY; | ||
179 | writel(tmp, vtg->regs + VTG_TOP_V_HD_1); | ||
180 | writel(tmp, vtg->regs + VTG_BOT_V_HD_1); | ||
156 | 181 | ||
157 | /* prepare VTG set 2 for for HD DCS */ | 182 | /* prepare VTG set 2 for for HD DCS */ |
158 | tmp = (mode->hsync_end - mode->hsync_start) << 16; | 183 | tmp = (mode->hsync_end - mode->hsync_start) << 16; |
@@ -311,7 +336,6 @@ static int vtg_probe(struct platform_device *pdev) | |||
311 | struct device_node *np; | 336 | struct device_node *np; |
312 | struct sti_vtg *vtg; | 337 | struct sti_vtg *vtg; |
313 | struct resource *res; | 338 | struct resource *res; |
314 | char irq_name[32]; | ||
315 | int ret; | 339 | int ret; |
316 | 340 | ||
317 | vtg = devm_kzalloc(dev, sizeof(*vtg), GFP_KERNEL); | 341 | vtg = devm_kzalloc(dev, sizeof(*vtg), GFP_KERNEL); |
@@ -342,13 +366,11 @@ static int vtg_probe(struct platform_device *pdev) | |||
342 | return vtg->irq; | 366 | return vtg->irq; |
343 | } | 367 | } |
344 | 368 | ||
345 | snprintf(irq_name, sizeof(irq_name), "vsync-%s", | ||
346 | dev_name(vtg->dev)); | ||
347 | |||
348 | RAW_INIT_NOTIFIER_HEAD(&vtg->notifier_list); | 369 | RAW_INIT_NOTIFIER_HEAD(&vtg->notifier_list); |
349 | 370 | ||
350 | ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq, | 371 | ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq, |
351 | vtg_irq_thread, IRQF_ONESHOT, irq_name, vtg); | 372 | vtg_irq_thread, IRQF_ONESHOT, |
373 | dev_name(dev), vtg); | ||
352 | if (IS_ERR_VALUE(ret)) { | 374 | if (IS_ERR_VALUE(ret)) { |
353 | DRM_ERROR("Failed to register VTG interrupt\n"); | 375 | DRM_ERROR("Failed to register VTG interrupt\n"); |
354 | return ret; | 376 | return ret; |