aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-04-22 05:47:40 -0400
committerDave Airlie <airlied@redhat.com>2013-04-22 05:47:40 -0400
commit64c026e28d68bf64b0a3c85e31d74c42a7cdecd3 (patch)
tree6e5d1e0ed2af12ff883641882734b908b2c952f1
parentf0aa848fe5f2ed2599b7d54a6d3719d9df0a0965 (diff)
parentb4e3a3e844a0e33cf106a1c9f27ff93340c37640 (diff)
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
Inki writes: This is initial pull request for Exynos. It includes a big change that it makes drm_display_mode for timings parameters to be used for exynos4 and exynos5 commonly and cleans up unnecessary codes. And also it adds device tree support for fimd to get timing values and interrupt source from dts file. In addition, one more patch, device tree support feature for Exynos FIMC, is being reviewed. This patch was posted a little ago like below, http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg17568.html So we are going to request git pull one more time after reviewed. * 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: drm/exynos: prepare FIMD clocks Revert "of/exynos_g2d: Add Bindings for exynos G2D driver" drm/exynos: drm_connector: Fix error check condition drm/exynos: drm_rotator: Fix incorrect usage of IS_ERR_OR_NULL drm/exynos: mixer: Fix incorrect usage of IS_ERR_OR_NULL drm/exynos: hdmi: Fix incorrect usage of IS_ERR_OR_NULL drm/exynos: change the method for getting the interrupt drm/exynos: enable OF_VIDEOMODE and FB_MODE_HELPERS for exynos drm fimd drm/exynos: Add display-timing node parsing using video helper function drm/exynos: hdmi: move mode_fixup to drm common hdmi drm/exynos: hdmi: using drm_display_mode timings for exynos4
-rw-r--r--Documentation/devicetree/bindings/drm/exynos/g2d.txt22
-rw-r--r--drivers/gpu/drm/exynos/Kconfig4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_connector.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c40
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_hdmi.c40
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_hdmi.h3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_rotator.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c704
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c14
9 files changed, 324 insertions, 507 deletions
diff --git a/Documentation/devicetree/bindings/drm/exynos/g2d.txt b/Documentation/devicetree/bindings/drm/exynos/g2d.txt
deleted file mode 100644
index 1eb124d35a99..000000000000
--- a/Documentation/devicetree/bindings/drm/exynos/g2d.txt
+++ /dev/null
@@ -1,22 +0,0 @@
1Samsung 2D Graphic Accelerator using DRM frame work
2
3Samsung FIMG2D is a graphics 2D accelerator which supports Bit Block Transfer.
4We set the drawing-context registers for configuring rendering parameters and
5then start rendering.
6This driver is for SOCs which contain G2D IPs with version 4.1.
7
8Required properties:
9 -compatible:
10 should be "samsung,exynos-g2d-41".
11 -reg:
12 physical base address of the controller and length
13 of memory mapped region.
14 -interrupts:
15 interrupt combiner values.
16
17Example:
18 g2d {
19 compatible = "samsung,exynos-g2d-41";
20 reg = <0x10850000 0x1000>;
21 interrupts = <0 91 0>;
22 };
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 046bcda36abe..406f32af8266 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -24,7 +24,9 @@ config DRM_EXYNOS_DMABUF
24 24
25config DRM_EXYNOS_FIMD 25config DRM_EXYNOS_FIMD
26 bool "Exynos DRM FIMD" 26 bool "Exynos DRM FIMD"
27 depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM 27 depends on OF && DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM
28 select OF_VIDEOMODE
29 select FB_MODE_HELPERS
28 help 30 help
29 Choose this option if you want to use Exynos FIMD for DRM. 31 Choose this option if you want to use Exynos FIMD for DRM.
30 32
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index 4c5b6859c9ea..8bcc13ac9f73 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -124,7 +124,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
124 } 124 }
125 125
126 count = drm_add_edid_modes(connector, edid); 126 count = drm_add_edid_modes(connector, edid);
127 if (count < 0) { 127 if (!count) {
128 DRM_ERROR("Add edid modes failed %d\n", count); 128 DRM_ERROR("Add edid modes failed %d\n", count);
129 goto out; 129 goto out;
130 } 130 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 98cc14725ba9..15e58f5abe02 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -20,6 +20,7 @@
20#include <linux/of_device.h> 20#include <linux/of_device.h>
21#include <linux/pm_runtime.h> 21#include <linux/pm_runtime.h>
22 22
23#include <video/of_display_timing.h>
23#include <video/samsung_fimd.h> 24#include <video/samsung_fimd.h>
24#include <drm/exynos_drm.h> 25#include <drm/exynos_drm.h>
25 26
@@ -884,10 +885,25 @@ static int fimd_probe(struct platform_device *pdev)
884 885
885 DRM_DEBUG_KMS("%s\n", __FILE__); 886 DRM_DEBUG_KMS("%s\n", __FILE__);
886 887
887 pdata = pdev->dev.platform_data; 888 if (pdev->dev.of_node) {
888 if (!pdata) { 889 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
889 dev_err(dev, "no platform data specified\n"); 890 if (!pdata) {
890 return -EINVAL; 891 DRM_ERROR("memory allocation for pdata failed\n");
892 return -ENOMEM;
893 }
894
895 ret = of_get_fb_videomode(dev->of_node, &pdata->panel.timing,
896 OF_USE_NATIVE_MODE);
897 if (ret) {
898 DRM_ERROR("failed: of_get_fb_videomode() : %d\n", ret);
899 return ret;
900 }
901 } else {
902 pdata = pdev->dev.platform_data;
903 if (!pdata) {
904 DRM_ERROR("no platform data specified\n");
905 return -EINVAL;
906 }
891 } 907 }
892 908
893 panel = &pdata->panel; 909 panel = &pdata->panel;
@@ -918,7 +934,7 @@ static int fimd_probe(struct platform_device *pdev)
918 if (IS_ERR(ctx->regs)) 934 if (IS_ERR(ctx->regs))
919 return PTR_ERR(ctx->regs); 935 return PTR_ERR(ctx->regs);
920 936
921 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 937 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "vsync");
922 if (!res) { 938 if (!res) {
923 dev_err(dev, "irq request failed.\n"); 939 dev_err(dev, "irq request failed.\n");
924 return -ENXIO; 940 return -ENXIO;
@@ -933,6 +949,16 @@ static int fimd_probe(struct platform_device *pdev)
933 return ret; 949 return ret;
934 } 950 }
935 951
952 ret = clk_prepare(ctx->bus_clk);
953 if (ret < 0)
954 return ret;
955
956 ret = clk_prepare(ctx->lcd_clk);
957 if (ret < 0) {
958 clk_unprepare(ctx->bus_clk);
959 return ret;
960 }
961
936 ctx->vidcon0 = pdata->vidcon0; 962 ctx->vidcon0 = pdata->vidcon0;
937 ctx->vidcon1 = pdata->vidcon1; 963 ctx->vidcon1 = pdata->vidcon1;
938 ctx->default_win = pdata->default_win; 964 ctx->default_win = pdata->default_win;
@@ -980,8 +1006,8 @@ static int fimd_remove(struct platform_device *pdev)
980 if (ctx->suspended) 1006 if (ctx->suspended)
981 goto out; 1007 goto out;
982 1008
983 clk_disable(ctx->lcd_clk); 1009 clk_unprepare(ctx->lcd_clk);
984 clk_disable(ctx->bus_clk); 1010 clk_unprepare(ctx->bus_clk);
985 1011
986 pm_runtime_set_suspended(dev); 1012 pm_runtime_set_suspended(dev);
987 pm_runtime_put_sync(dev); 1013 pm_runtime_put_sync(dev);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index 7c27df03c9ff..5285509e4b34 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -205,13 +205,45 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
205 const struct drm_display_mode *mode, 205 const struct drm_display_mode *mode,
206 struct drm_display_mode *adjusted_mode) 206 struct drm_display_mode *adjusted_mode)
207{ 207{
208 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 208 struct drm_display_mode *m;
209 int mode_ok;
209 210
210 DRM_DEBUG_KMS("%s\n", __FILE__); 211 DRM_DEBUG_KMS("%s\n", __FILE__);
211 212
212 if (hdmi_ops && hdmi_ops->mode_fixup) 213 drm_mode_set_crtcinfo(adjusted_mode, 0);
213 hdmi_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, mode, 214
214 adjusted_mode); 215 mode_ok = drm_hdmi_check_timing(subdrv_dev, adjusted_mode);
216
217 /* just return if user desired mode exists. */
218 if (mode_ok == 0)
219 return;
220
221 /*
222 * otherwise, find the most suitable mode among modes and change it
223 * to adjusted_mode.
224 */
225 list_for_each_entry(m, &connector->modes, head) {
226 mode_ok = drm_hdmi_check_timing(subdrv_dev, m);
227
228 if (mode_ok == 0) {
229 struct drm_mode_object base;
230 struct list_head head;
231
232 DRM_INFO("desired mode doesn't exist so\n");
233 DRM_INFO("use the most suitable mode among modes.\n");
234
235 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
236 m->hdisplay, m->vdisplay, m->vrefresh);
237
238 /* preserve display mode header while copying. */
239 head = adjusted_mode->head;
240 base = adjusted_mode->base;
241 memcpy(adjusted_mode, m, sizeof(*m));
242 adjusted_mode->head = head;
243 adjusted_mode->base = base;
244 break;
245 }
246 }
215} 247}
216 248
217static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode) 249static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
index b7faa3662307..6b709440df4c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
@@ -36,9 +36,6 @@ struct exynos_hdmi_ops {
36 int (*power_on)(void *ctx, int mode); 36 int (*power_on)(void *ctx, int mode);
37 37
38 /* manager */ 38 /* manager */
39 void (*mode_fixup)(void *ctx, struct drm_connector *connector,
40 const struct drm_display_mode *mode,
41 struct drm_display_mode *adjusted_mode);
42 void (*mode_set)(void *ctx, void *mode); 39 void (*mode_set)(void *ctx, void *mode);
43 void (*get_max_resol)(void *ctx, unsigned int *width, 40 void (*get_max_resol)(void *ctx, unsigned int *width,
44 unsigned int *height); 41 unsigned int *height);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index a40b9fb60240..947f09f15ad1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -674,7 +674,7 @@ static int rotator_probe(struct platform_device *pdev)
674 } 674 }
675 675
676 rot->clock = devm_clk_get(dev, "rotator"); 676 rot->clock = devm_clk_get(dev, "rotator");
677 if (IS_ERR_OR_NULL(rot->clock)) { 677 if (IS_ERR(rot->clock)) {
678 dev_err(dev, "failed to get clock\n"); 678 dev_err(dev, "failed to get clock\n");
679 ret = PTR_ERR(rot->clock); 679 ret = PTR_ERR(rot->clock);
680 goto err_clk_get; 680 goto err_clk_get;
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 2c5f266154ad..93b70e9f6e99 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -108,7 +108,20 @@ struct hdmi_tg_regs {
108 u8 tg_3d[1]; 108 u8 tg_3d[1];
109}; 109};
110 110
111struct hdmi_core_regs { 111struct hdmi_v13_core_regs {
112 u8 h_blank[2];
113 u8 v_blank[3];
114 u8 h_v_line[3];
115 u8 vsync_pol[1];
116 u8 int_pro_mode[1];
117 u8 v_blank_f[3];
118 u8 h_sync_gen[3];
119 u8 v_sync_gen1[3];
120 u8 v_sync_gen2[3];
121 u8 v_sync_gen3[3];
122};
123
124struct hdmi_v14_core_regs {
112 u8 h_blank[2]; 125 u8 h_blank[2];
113 u8 v2_blank[2]; 126 u8 v2_blank[2];
114 u8 v1_blank[2]; 127 u8 v1_blank[2];
@@ -147,11 +160,23 @@ struct hdmi_core_regs {
147 u8 vact_space_6[2]; 160 u8 vact_space_6[2];
148}; 161};
149 162
163struct hdmi_v13_conf {
164 struct hdmi_v13_core_regs core;
165 struct hdmi_tg_regs tg;
166};
167
150struct hdmi_v14_conf { 168struct hdmi_v14_conf {
151 int pixel_clock; 169 struct hdmi_v14_core_regs core;
152 struct hdmi_core_regs core;
153 struct hdmi_tg_regs tg; 170 struct hdmi_tg_regs tg;
171};
172
173struct hdmi_conf_regs {
174 int pixel_clock;
154 int cea_video_id; 175 int cea_video_id;
176 union {
177 struct hdmi_v13_conf v13_conf;
178 struct hdmi_v14_conf v14_conf;
179 } conf;
155}; 180};
156 181
157struct hdmi_context { 182struct hdmi_context {
@@ -169,9 +194,8 @@ struct hdmi_context {
169 struct i2c_client *ddc_port; 194 struct i2c_client *ddc_port;
170 struct i2c_client *hdmiphy_port; 195 struct i2c_client *hdmiphy_port;
171 196
172 /* current hdmiphy conf index */ 197 /* current hdmiphy conf regs */
173 int cur_conf; 198 struct hdmi_conf_regs mode_conf;
174 struct hdmi_v14_conf mode_conf;
175 199
176 struct hdmi_resources res; 200 struct hdmi_resources res;
177 201
@@ -180,292 +204,60 @@ struct hdmi_context {
180 enum hdmi_type type; 204 enum hdmi_type type;
181}; 205};
182 206
183/* HDMI Version 1.3 */ 207struct hdmiphy_config {
184static const u8 hdmiphy_v13_conf27[32] = { 208 int pixel_clock;
185 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 209 u8 conf[32];
186 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
187 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
188 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
189};
190
191static const u8 hdmiphy_v13_conf27_027[32] = {
192 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
193 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
194 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
195 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
196};
197
198static const u8 hdmiphy_v13_conf74_175[32] = {
199 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
200 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
201 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
202 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
203};
204
205static const u8 hdmiphy_v13_conf74_25[32] = {
206 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
207 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
208 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
209 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
210};
211
212static const u8 hdmiphy_v13_conf148_5[32] = {
213 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
214 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
215 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
216 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
217};
218
219struct hdmi_v13_tg_regs {
220 u8 cmd;
221 u8 h_fsz_l;
222 u8 h_fsz_h;
223 u8 hact_st_l;
224 u8 hact_st_h;
225 u8 hact_sz_l;
226 u8 hact_sz_h;
227 u8 v_fsz_l;
228 u8 v_fsz_h;
229 u8 vsync_l;
230 u8 vsync_h;
231 u8 vsync2_l;
232 u8 vsync2_h;
233 u8 vact_st_l;
234 u8 vact_st_h;
235 u8 vact_sz_l;
236 u8 vact_sz_h;
237 u8 field_chg_l;
238 u8 field_chg_h;
239 u8 vact_st2_l;
240 u8 vact_st2_h;
241 u8 vsync_top_hdmi_l;
242 u8 vsync_top_hdmi_h;
243 u8 vsync_bot_hdmi_l;
244 u8 vsync_bot_hdmi_h;
245 u8 field_top_hdmi_l;
246 u8 field_top_hdmi_h;
247 u8 field_bot_hdmi_l;
248 u8 field_bot_hdmi_h;
249};
250
251struct hdmi_v13_core_regs {
252 u8 h_blank[2];
253 u8 v_blank[3];
254 u8 h_v_line[3];
255 u8 vsync_pol[1];
256 u8 int_pro_mode[1];
257 u8 v_blank_f[3];
258 u8 h_sync_gen[3];
259 u8 v_sync_gen1[3];
260 u8 v_sync_gen2[3];
261 u8 v_sync_gen3[3];
262};
263
264struct hdmi_v13_preset_conf {
265 struct hdmi_v13_core_regs core;
266 struct hdmi_v13_tg_regs tg;
267};
268
269struct hdmi_v13_conf {
270 int width;
271 int height;
272 int vrefresh;
273 bool interlace;
274 int cea_video_id;
275 const u8 *hdmiphy_data;
276 const struct hdmi_v13_preset_conf *conf;
277};
278
279static const struct hdmi_v13_preset_conf hdmi_v13_conf_480p = {
280 .core = {
281 .h_blank = {0x8a, 0x00},
282 .v_blank = {0x0d, 0x6a, 0x01},
283 .h_v_line = {0x0d, 0xa2, 0x35},
284 .vsync_pol = {0x01},
285 .int_pro_mode = {0x00},
286 .v_blank_f = {0x00, 0x00, 0x00},
287 .h_sync_gen = {0x0e, 0x30, 0x11},
288 .v_sync_gen1 = {0x0f, 0x90, 0x00},
289 /* other don't care */
290 },
291 .tg = {
292 0x00, /* cmd */
293 0x5a, 0x03, /* h_fsz */
294 0x8a, 0x00, 0xd0, 0x02, /* hact */
295 0x0d, 0x02, /* v_fsz */
296 0x01, 0x00, 0x33, 0x02, /* vsync */
297 0x2d, 0x00, 0xe0, 0x01, /* vact */
298 0x33, 0x02, /* field_chg */
299 0x49, 0x02, /* vact_st2 */
300 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
301 0x01, 0x00, 0x33, 0x02, /* field top/bot */
302 },
303};
304
305static const struct hdmi_v13_preset_conf hdmi_v13_conf_720p60 = {
306 .core = {
307 .h_blank = {0x72, 0x01},
308 .v_blank = {0xee, 0xf2, 0x00},
309 .h_v_line = {0xee, 0x22, 0x67},
310 .vsync_pol = {0x00},
311 .int_pro_mode = {0x00},
312 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
313 .h_sync_gen = {0x6c, 0x50, 0x02},
314 .v_sync_gen1 = {0x0a, 0x50, 0x00},
315 .v_sync_gen2 = {0x01, 0x10, 0x00},
316 .v_sync_gen3 = {0x01, 0x10, 0x00},
317 /* other don't care */
318 },
319 .tg = {
320 0x00, /* cmd */
321 0x72, 0x06, /* h_fsz */
322 0x71, 0x01, 0x01, 0x05, /* hact */
323 0xee, 0x02, /* v_fsz */
324 0x01, 0x00, 0x33, 0x02, /* vsync */
325 0x1e, 0x00, 0xd0, 0x02, /* vact */
326 0x33, 0x02, /* field_chg */
327 0x49, 0x02, /* vact_st2 */
328 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
329 0x01, 0x00, 0x33, 0x02, /* field top/bot */
330 },
331};
332
333static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i50 = {
334 .core = {
335 .h_blank = {0xd0, 0x02},
336 .v_blank = {0x32, 0xB2, 0x00},
337 .h_v_line = {0x65, 0x04, 0xa5},
338 .vsync_pol = {0x00},
339 .int_pro_mode = {0x01},
340 .v_blank_f = {0x49, 0x2A, 0x23},
341 .h_sync_gen = {0x0E, 0xEA, 0x08},
342 .v_sync_gen1 = {0x07, 0x20, 0x00},
343 .v_sync_gen2 = {0x39, 0x42, 0x23},
344 .v_sync_gen3 = {0x38, 0x87, 0x73},
345 /* other don't care */
346 },
347 .tg = {
348 0x00, /* cmd */
349 0x50, 0x0A, /* h_fsz */
350 0xCF, 0x02, 0x81, 0x07, /* hact */
351 0x65, 0x04, /* v_fsz */
352 0x01, 0x00, 0x33, 0x02, /* vsync */
353 0x16, 0x00, 0x1c, 0x02, /* vact */
354 0x33, 0x02, /* field_chg */
355 0x49, 0x02, /* vact_st2 */
356 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
357 0x01, 0x00, 0x33, 0x02, /* field top/bot */
358 },
359}; 210};
360 211
361static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p50 = { 212/* list of phy config settings */
362 .core = { 213static const struct hdmiphy_config hdmiphy_v13_configs[] = {
363 .h_blank = {0xd0, 0x02}, 214 {
364 .v_blank = {0x65, 0x6c, 0x01}, 215 .pixel_clock = 27000000,
365 .h_v_line = {0x65, 0x04, 0xa5}, 216 .conf = {
366 .vsync_pol = {0x00}, 217 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
367 .int_pro_mode = {0x00}, 218 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
368 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */ 219 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
369 .h_sync_gen = {0x0e, 0xea, 0x08}, 220 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
370 .v_sync_gen1 = {0x09, 0x40, 0x00}, 221 },
371 .v_sync_gen2 = {0x01, 0x10, 0x00},
372 .v_sync_gen3 = {0x01, 0x10, 0x00},
373 /* other don't care */
374 },
375 .tg = {
376 0x00, /* cmd */
377 0x50, 0x0A, /* h_fsz */
378 0xCF, 0x02, 0x81, 0x07, /* hact */
379 0x65, 0x04, /* v_fsz */
380 0x01, 0x00, 0x33, 0x02, /* vsync */
381 0x2d, 0x00, 0x38, 0x04, /* vact */
382 0x33, 0x02, /* field_chg */
383 0x48, 0x02, /* vact_st2 */
384 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
385 0x01, 0x00, 0x33, 0x02, /* field top/bot */
386 }, 222 },
387}; 223 {
388 224 .pixel_clock = 27027000,
389static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i60 = { 225 .conf = {
390 .core = { 226 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
391 .h_blank = {0x18, 0x01}, 227 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
392 .v_blank = {0x32, 0xB2, 0x00}, 228 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
393 .h_v_line = {0x65, 0x84, 0x89}, 229 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
394 .vsync_pol = {0x00}, 230 },
395 .int_pro_mode = {0x01},
396 .v_blank_f = {0x49, 0x2A, 0x23},
397 .h_sync_gen = {0x56, 0x08, 0x02},
398 .v_sync_gen1 = {0x07, 0x20, 0x00},
399 .v_sync_gen2 = {0x39, 0x42, 0x23},
400 .v_sync_gen3 = {0xa4, 0x44, 0x4a},
401 /* other don't care */
402 }, 231 },
403 .tg = { 232 {
404 0x00, /* cmd */ 233 .pixel_clock = 74176000,
405 0x98, 0x08, /* h_fsz */ 234 .conf = {
406 0x17, 0x01, 0x81, 0x07, /* hact */ 235 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
407 0x65, 0x04, /* v_fsz */ 236 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
408 0x01, 0x00, 0x33, 0x02, /* vsync */ 237 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
409 0x16, 0x00, 0x1c, 0x02, /* vact */ 238 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
410 0x33, 0x02, /* field_chg */ 239 },
411 0x49, 0x02, /* vact_st2 */
412 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
413 0x01, 0x00, 0x33, 0x02, /* field top/bot */
414 }, 240 },
415}; 241 {
416 242 .pixel_clock = 74250000,
417static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = { 243 .conf = {
418 .core = { 244 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
419 .h_blank = {0x18, 0x01}, 245 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
420 .v_blank = {0x65, 0x6c, 0x01}, 246 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
421 .h_v_line = {0x65, 0x84, 0x89}, 247 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
422 .vsync_pol = {0x00}, 248 },
423 .int_pro_mode = {0x00},
424 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
425 .h_sync_gen = {0x56, 0x08, 0x02},
426 .v_sync_gen1 = {0x09, 0x40, 0x00},
427 .v_sync_gen2 = {0x01, 0x10, 0x00},
428 .v_sync_gen3 = {0x01, 0x10, 0x00},
429 /* other don't care */
430 }, 249 },
431 .tg = { 250 {
432 0x00, /* cmd */ 251 .pixel_clock = 148500000,
433 0x98, 0x08, /* h_fsz */ 252 .conf = {
434 0x17, 0x01, 0x81, 0x07, /* hact */ 253 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
435 0x65, 0x04, /* v_fsz */ 254 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
436 0x01, 0x00, 0x33, 0x02, /* vsync */ 255 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
437 0x2d, 0x00, 0x38, 0x04, /* vact */ 256 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
438 0x33, 0x02, /* field_chg */ 257 },
439 0x48, 0x02, /* vact_st2 */
440 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
441 0x01, 0x00, 0x33, 0x02, /* field top/bot */
442 }, 258 },
443}; 259};
444 260
445static const struct hdmi_v13_conf hdmi_v13_confs[] = {
446 { 1280, 720, 60, false, 4, hdmiphy_v13_conf74_25,
447 &hdmi_v13_conf_720p60 },
448 { 1280, 720, 50, false, 19, hdmiphy_v13_conf74_25,
449 &hdmi_v13_conf_720p60 },
450 { 720, 480, 60, false, 3, hdmiphy_v13_conf27_027,
451 &hdmi_v13_conf_480p },
452 { 1920, 1080, 50, true, 20, hdmiphy_v13_conf74_25,
453 &hdmi_v13_conf_1080i50 },
454 { 1920, 1080, 50, false, 31, hdmiphy_v13_conf148_5,
455 &hdmi_v13_conf_1080p50 },
456 { 1920, 1080, 60, true, 5, hdmiphy_v13_conf74_25,
457 &hdmi_v13_conf_1080i60 },
458 { 1920, 1080, 60, false, 16, hdmiphy_v13_conf148_5,
459 &hdmi_v13_conf_1080p60 },
460};
461
462/* HDMI Version 1.4 */
463struct hdmiphy_config {
464 int pixel_clock;
465 u8 conf[32];
466};
467
468/* list of all required phy config settings */
469static const struct hdmiphy_config hdmiphy_v14_configs[] = { 261static const struct hdmiphy_config hdmiphy_v14_configs[] = {
470 { 262 {
471 .pixel_clock = 25200000, 263 .pixel_clock = 25200000,
@@ -873,22 +665,6 @@ static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
873 hdmi_v14_regs_dump(hdata, prefix); 665 hdmi_v14_regs_dump(hdata, prefix);
874} 666}
875 667
876static int hdmi_v13_conf_index(struct drm_display_mode *mode)
877{
878 int i;
879
880 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
881 if (hdmi_v13_confs[i].width == mode->hdisplay &&
882 hdmi_v13_confs[i].height == mode->vdisplay &&
883 hdmi_v13_confs[i].vrefresh == mode->vrefresh &&
884 hdmi_v13_confs[i].interlace ==
885 ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
886 true : false))
887 return i;
888
889 return -EINVAL;
890}
891
892static u8 hdmi_chksum(struct hdmi_context *hdata, 668static u8 hdmi_chksum(struct hdmi_context *hdata,
893 u32 start, u8 len, u32 hdr_sum) 669 u32 start, u8 len, u32 hdr_sum)
894{ 670{
@@ -943,11 +719,7 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
943 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), aspect_ratio | 719 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), aspect_ratio |
944 AVI_SAME_AS_PIC_ASPECT_RATIO); 720 AVI_SAME_AS_PIC_ASPECT_RATIO);
945 721
946 if (hdata->type == HDMI_TYPE13) 722 vic = hdata->mode_conf.cea_video_id;
947 vic = hdmi_v13_confs[hdata->cur_conf].cea_video_id;
948 else
949 vic = hdata->mode_conf.cea_video_id;
950
951 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic); 723 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
952 724
953 chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1), 725 chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
@@ -1000,63 +772,34 @@ static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
1000 return raw_edid; 772 return raw_edid;
1001} 773}
1002 774
1003static int hdmi_v13_check_timing(struct fb_videomode *check_timing) 775static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
1004{ 776{
1005 int i; 777 const struct hdmiphy_config *confs;
778 int count, i;
1006 779
1007 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n", 780 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1008 check_timing->xres, check_timing->yres,
1009 check_timing->refresh, (check_timing->vmode &
1010 FB_VMODE_INTERLACED) ? true : false);
1011
1012 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1013 if (hdmi_v13_confs[i].width == check_timing->xres &&
1014 hdmi_v13_confs[i].height == check_timing->yres &&
1015 hdmi_v13_confs[i].vrefresh == check_timing->refresh &&
1016 hdmi_v13_confs[i].interlace ==
1017 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1018 true : false))
1019 return 0;
1020
1021 /* TODO */
1022
1023 return -EINVAL;
1024}
1025 781
1026static int hdmi_v14_find_phy_conf(int pixel_clock) 782 if (hdata->type == HDMI_TYPE13) {
1027{ 783 confs = hdmiphy_v13_configs;
1028 int i; 784 count = ARRAY_SIZE(hdmiphy_v13_configs);
785 } else if (hdata->type == HDMI_TYPE14) {
786 confs = hdmiphy_v14_configs;
787 count = ARRAY_SIZE(hdmiphy_v14_configs);
788 } else
789 return -EINVAL;
1029 790
1030 for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++) { 791 for (i = 0; i < count; i++)
1031 if (hdmiphy_v14_configs[i].pixel_clock == pixel_clock) 792 if (confs[i].pixel_clock == pixel_clock)
1032 return i; 793 return i;
1033 }
1034 794
1035 DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock); 795 DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
1036 return -EINVAL; 796 return -EINVAL;
1037} 797}
1038 798
1039static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
1040{
1041 int i;
1042
1043 DRM_DEBUG_KMS("mode: xres=%d, yres=%d, refresh=%d, clock=%d, intl=%d\n",
1044 check_timing->xres, check_timing->yres,
1045 check_timing->refresh, check_timing->pixclock,
1046 (check_timing->vmode & FB_VMODE_INTERLACED) ?
1047 true : false);
1048
1049 for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++)
1050 if (hdmiphy_v14_configs[i].pixel_clock ==
1051 check_timing->pixclock)
1052 return 0;
1053
1054 return -EINVAL;
1055}
1056
1057static int hdmi_check_timing(void *ctx, struct fb_videomode *timing) 799static int hdmi_check_timing(void *ctx, struct fb_videomode *timing)
1058{ 800{
1059 struct hdmi_context *hdata = ctx; 801 struct hdmi_context *hdata = ctx;
802 int ret;
1060 803
1061 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 804 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1062 805
@@ -1064,10 +807,10 @@ static int hdmi_check_timing(void *ctx, struct fb_videomode *timing)
1064 timing->yres, timing->refresh, 807 timing->yres, timing->refresh,
1065 timing->vmode); 808 timing->vmode);
1066 809
1067 if (hdata->type == HDMI_TYPE13) 810 ret = hdmi_find_phy_conf(hdata, timing->pixclock);
1068 return hdmi_v13_check_timing(timing); 811 if (ret < 0)
1069 else 812 return ret;
1070 return hdmi_v14_check_timing(timing); 813 return 0;
1071} 814}
1072 815
1073static void hdmi_set_acr(u32 freq, u8 *acr) 816static void hdmi_set_acr(u32 freq, u8 *acr)
@@ -1301,10 +1044,9 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
1301 1044
1302static void hdmi_v13_timing_apply(struct hdmi_context *hdata) 1045static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
1303{ 1046{
1304 const struct hdmi_v13_preset_conf *conf = 1047 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1305 hdmi_v13_confs[hdata->cur_conf].conf; 1048 const struct hdmi_v13_core_regs *core =
1306 const struct hdmi_v13_core_regs *core = &conf->core; 1049 &hdata->mode_conf.conf.v13_conf.core;
1307 const struct hdmi_v13_tg_regs *tg = &conf->tg;
1308 int tries; 1050 int tries;
1309 1051
1310 /* setting core registers */ 1052 /* setting core registers */
@@ -1334,34 +1076,34 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
1334 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]); 1076 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1335 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]); 1077 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
1336 /* Timing generator registers */ 1078 /* Timing generator registers */
1337 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l); 1079 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1338 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h); 1080 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1339 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l); 1081 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1340 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h); 1082 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1341 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l); 1083 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1342 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h); 1084 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1343 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l); 1085 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1344 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h); 1086 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1345 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l); 1087 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1346 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h); 1088 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1347 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l); 1089 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1348 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h); 1090 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1349 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l); 1091 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1350 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h); 1092 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1351 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l); 1093 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1352 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h); 1094 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1353 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l); 1095 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1354 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h); 1096 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1355 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l); 1097 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1356 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h); 1098 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1357 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l); 1099 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1358 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h); 1100 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1359 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l); 1101 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1360 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h); 1102 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1361 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l); 1103 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1362 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h); 1104 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1363 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l); 1105 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1364 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h); 1106 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
1365 1107
1366 /* waiting for HDMIPHY's PLL to get to steady state */ 1108 /* waiting for HDMIPHY's PLL to get to steady state */
1367 for (tries = 100; tries; --tries) { 1109 for (tries = 100; tries; --tries) {
@@ -1391,8 +1133,9 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
1391 1133
1392static void hdmi_v14_timing_apply(struct hdmi_context *hdata) 1134static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
1393{ 1135{
1394 struct hdmi_core_regs *core = &hdata->mode_conf.core; 1136 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1395 struct hdmi_tg_regs *tg = &hdata->mode_conf.tg; 1137 const struct hdmi_v14_core_regs *core =
1138 &hdata->mode_conf.conf.v14_conf.core;
1396 int tries; 1139 int tries;
1397 1140
1398 /* setting core registers */ 1141 /* setting core registers */
@@ -1624,15 +1367,15 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1624 } 1367 }
1625 1368
1626 /* pixel clock */ 1369 /* pixel clock */
1370 i = hdmi_find_phy_conf(hdata, hdata->mode_conf.pixel_clock);
1371 if (i < 0) {
1372 DRM_ERROR("failed to find hdmiphy conf\n");
1373 return;
1374 }
1375
1627 if (hdata->type == HDMI_TYPE13) { 1376 if (hdata->type == HDMI_TYPE13) {
1628 hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data; 1377 hdmiphy_data = hdmiphy_v13_configs[i].conf;
1629 } else { 1378 } else {
1630 i = hdmi_v14_find_phy_conf(hdata->mode_conf.pixel_clock);
1631 if (i < 0) {
1632 DRM_ERROR("failed to find hdmiphy conf\n");
1633 return;
1634 }
1635
1636 hdmiphy_data = hdmiphy_v14_configs[i].conf; 1379 hdmiphy_data = hdmiphy_v14_configs[i].conf;
1637 } 1380 }
1638 1381
@@ -1687,75 +1430,121 @@ static void hdmi_conf_apply(struct hdmi_context *hdata)
1687 hdmi_regs_dump(hdata, "start"); 1430 hdmi_regs_dump(hdata, "start");
1688} 1431}
1689 1432
1690static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, 1433static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value)
1691 const struct drm_display_mode *mode,
1692 struct drm_display_mode *adjusted_mode)
1693{ 1434{
1694 struct drm_display_mode *m; 1435 int i;
1695 struct hdmi_context *hdata = ctx; 1436 BUG_ON(num_bytes > 4);
1696 int index; 1437 for (i = 0; i < num_bytes; i++)
1438 reg_pair[i] = (value >> (8 * i)) & 0xff;
1439}
1697 1440
1698 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 1441static void hdmi_v13_mode_set(struct hdmi_context *hdata,
1442 struct drm_display_mode *m)
1443{
1444 struct hdmi_v13_core_regs *core = &hdata->mode_conf.conf.v13_conf.core;
1445 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1446 unsigned int val;
1699 1447
1700 drm_mode_set_crtcinfo(adjusted_mode, 0); 1448 hdata->mode_conf.cea_video_id =
1449 drm_match_cea_mode((struct drm_display_mode *)m);
1450 hdata->mode_conf.pixel_clock = m->clock * 1000;
1701 1451
1702 if (hdata->type == HDMI_TYPE13) 1452 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1703 index = hdmi_v13_conf_index(adjusted_mode); 1453 hdmi_set_reg(core->h_v_line, 3, (m->htotal << 12) | m->vtotal);
1704 else
1705 index = hdmi_v14_find_phy_conf(adjusted_mode->clock * 1000);
1706 1454
1707 /* just return if user desired mode exists. */ 1455 val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
1708 if (index >= 0) 1456 hdmi_set_reg(core->vsync_pol, 1, val);
1709 return; 1457
1458 val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
1459 hdmi_set_reg(core->int_pro_mode, 1, val);
1460
1461 val = (m->hsync_start - m->hdisplay - 2);
1462 val |= ((m->hsync_end - m->hdisplay - 2) << 10);
1463 val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
1464 hdmi_set_reg(core->h_sync_gen, 3, val);
1710 1465
1711 /* 1466 /*
1712 * otherwise, find the most suitable mode among modes and change it 1467 * Quirk requirement for exynos HDMI IP design,
1713 * to adjusted_mode. 1468 * 2 pixels less than the actual calculation for hsync_start
1469 * and end.
1714 */ 1470 */
1715 list_for_each_entry(m, &connector->modes, head) { 1471
1716 if (hdata->type == HDMI_TYPE13) 1472 /* Following values & calculations differ for different type of modes */
1717 index = hdmi_v13_conf_index(m); 1473 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1718 else 1474 /* Interlaced Mode */
1719 index = hdmi_v14_find_phy_conf(m->clock * 1000); 1475 val = ((m->vsync_end - m->vdisplay) / 2);
1720 1476 val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
1721 if (index >= 0) { 1477 hdmi_set_reg(core->v_sync_gen1, 3, val);
1722 struct drm_mode_object base; 1478
1723 struct list_head head; 1479 val = m->vtotal / 2;
1724 1480 val |= ((m->vtotal - m->vdisplay) / 2) << 11;
1725 DRM_INFO("desired mode doesn't exist so\n"); 1481 hdmi_set_reg(core->v_blank, 3, val);
1726 DRM_INFO("use the most suitable mode among modes.\n"); 1482
1727 1483 val = (m->vtotal +
1728 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n", 1484 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
1729 m->hdisplay, m->vdisplay, m->vrefresh); 1485 val |= m->vtotal << 11;
1730 1486 hdmi_set_reg(core->v_blank_f, 3, val);
1731 /* preserve display mode header while copying. */ 1487
1732 head = adjusted_mode->head; 1488 val = ((m->vtotal / 2) + 7);
1733 base = adjusted_mode->base; 1489 val |= ((m->vtotal / 2) + 2) << 12;
1734 memcpy(adjusted_mode, m, sizeof(*m)); 1490 hdmi_set_reg(core->v_sync_gen2, 3, val);
1735 adjusted_mode->head = head; 1491
1736 adjusted_mode->base = base; 1492 val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
1737 break; 1493 val |= ((m->htotal / 2) +
1738 } 1494 (m->hsync_start - m->hdisplay)) << 12;
1495 hdmi_set_reg(core->v_sync_gen3, 3, val);
1496
1497 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1498 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
1499
1500 hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
1501 } else {
1502 /* Progressive Mode */
1503
1504 val = m->vtotal;
1505 val |= (m->vtotal - m->vdisplay) << 11;
1506 hdmi_set_reg(core->v_blank, 3, val);
1507
1508 hdmi_set_reg(core->v_blank_f, 3, 0);
1509
1510 val = (m->vsync_end - m->vdisplay);
1511 val |= ((m->vsync_start - m->vdisplay) << 12);
1512 hdmi_set_reg(core->v_sync_gen1, 3, val);
1513
1514 hdmi_set_reg(core->v_sync_gen2, 3, 0x1001);/* Reset value */
1515 hdmi_set_reg(core->v_sync_gen3, 3, 0x1001);/* Reset value */
1516 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1517 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1518 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1739 } 1519 }
1740}
1741 1520
1742static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value) 1521 /* Timing generator registers */
1743{ 1522 hdmi_set_reg(tg->cmd, 1, 0x0);
1744 int i; 1523 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1745 BUG_ON(num_bytes > 4); 1524 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1746 for (i = 0; i < num_bytes; i++) 1525 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1747 reg_pair[i] = (value >> (8 * i)) & 0xff; 1526 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1527 hdmi_set_reg(tg->vsync, 2, 0x1);
1528 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1529 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1530 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
1531 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1532 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
1533 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
1534 hdmi_set_reg(tg->tg_3d, 1, 0x0); /* Not used */
1748} 1535}
1749 1536
1750static void hdmi_v14_mode_set(struct hdmi_context *hdata, 1537static void hdmi_v14_mode_set(struct hdmi_context *hdata,
1751 struct drm_display_mode *m) 1538 struct drm_display_mode *m)
1752{ 1539{
1753 struct hdmi_core_regs *core = &hdata->mode_conf.core; 1540 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1754 struct hdmi_tg_regs *tg = &hdata->mode_conf.tg; 1541 struct hdmi_v14_core_regs *core =
1755 1542 &hdata->mode_conf.conf.v14_conf.core;
1756 hdata->mode_conf.cea_video_id = drm_match_cea_mode(m);
1757 1543
1544 hdata->mode_conf.cea_video_id =
1545 drm_match_cea_mode((struct drm_display_mode *)m);
1758 hdata->mode_conf.pixel_clock = m->clock * 1000; 1546 hdata->mode_conf.pixel_clock = m->clock * 1000;
1547
1759 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay); 1548 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1760 hdmi_set_reg(core->v_line, 2, m->vtotal); 1549 hdmi_set_reg(core->v_line, 2, m->vtotal);
1761 hdmi_set_reg(core->h_line, 2, m->htotal); 1550 hdmi_set_reg(core->h_line, 2, m->htotal);
@@ -1852,22 +1641,20 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
1852 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */ 1641 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
1853 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */ 1642 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
1854 hdmi_set_reg(tg->tg_3d, 1, 0x0); 1643 hdmi_set_reg(tg->tg_3d, 1, 0x0);
1855
1856} 1644}
1857 1645
1858static void hdmi_mode_set(void *ctx, void *mode) 1646static void hdmi_mode_set(void *ctx, void *mode)
1859{ 1647{
1860 struct hdmi_context *hdata = ctx; 1648 struct hdmi_context *hdata = ctx;
1861 int conf_idx; 1649 struct drm_display_mode *m = mode;
1862 1650
1863 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 1651 DRM_DEBUG_KMS("[%s]: xres=%d, yres=%d, refresh=%d, intl=%s\n",
1652 __func__, m->hdisplay, m->vdisplay,
1653 m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
1654 "INTERLACED" : "PROGERESSIVE");
1864 1655
1865 if (hdata->type == HDMI_TYPE13) { 1656 if (hdata->type == HDMI_TYPE13) {
1866 conf_idx = hdmi_v13_conf_index(mode); 1657 hdmi_v13_mode_set(hdata, mode);
1867 if (conf_idx >= 0)
1868 hdata->cur_conf = conf_idx;
1869 else
1870 DRM_DEBUG_KMS("not supported mode\n");
1871 } else { 1658 } else {
1872 hdmi_v14_mode_set(hdata, mode); 1659 hdmi_v14_mode_set(hdata, mode);
1873 } 1660 }
@@ -1983,7 +1770,6 @@ static struct exynos_hdmi_ops hdmi_ops = {
1983 .check_timing = hdmi_check_timing, 1770 .check_timing = hdmi_check_timing,
1984 1771
1985 /* manager */ 1772 /* manager */
1986 .mode_fixup = hdmi_mode_fixup,
1987 .mode_set = hdmi_mode_set, 1773 .mode_set = hdmi_mode_set,
1988 .get_max_resol = hdmi_get_max_resol, 1774 .get_max_resol = hdmi_get_max_resol,
1989 .commit = hdmi_commit, 1775 .commit = hdmi_commit,
@@ -2023,27 +1809,27 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
2023 1809
2024 /* get clocks, power */ 1810 /* get clocks, power */
2025 res->hdmi = devm_clk_get(dev, "hdmi"); 1811 res->hdmi = devm_clk_get(dev, "hdmi");
2026 if (IS_ERR_OR_NULL(res->hdmi)) { 1812 if (IS_ERR(res->hdmi)) {
2027 DRM_ERROR("failed to get clock 'hdmi'\n"); 1813 DRM_ERROR("failed to get clock 'hdmi'\n");
2028 goto fail; 1814 goto fail;
2029 } 1815 }
2030 res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi"); 1816 res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
2031 if (IS_ERR_OR_NULL(res->sclk_hdmi)) { 1817 if (IS_ERR(res->sclk_hdmi)) {
2032 DRM_ERROR("failed to get clock 'sclk_hdmi'\n"); 1818 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
2033 goto fail; 1819 goto fail;
2034 } 1820 }
2035 res->sclk_pixel = devm_clk_get(dev, "sclk_pixel"); 1821 res->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
2036 if (IS_ERR_OR_NULL(res->sclk_pixel)) { 1822 if (IS_ERR(res->sclk_pixel)) {
2037 DRM_ERROR("failed to get clock 'sclk_pixel'\n"); 1823 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
2038 goto fail; 1824 goto fail;
2039 } 1825 }
2040 res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy"); 1826 res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
2041 if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) { 1827 if (IS_ERR(res->sclk_hdmiphy)) {
2042 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n"); 1828 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
2043 goto fail; 1829 goto fail;
2044 } 1830 }
2045 res->hdmiphy = devm_clk_get(dev, "hdmiphy"); 1831 res->hdmiphy = devm_clk_get(dev, "hdmiphy");
2046 if (IS_ERR_OR_NULL(res->hdmiphy)) { 1832 if (IS_ERR(res->hdmiphy)) {
2047 DRM_ERROR("failed to get clock 'hdmiphy'\n"); 1833 DRM_ERROR("failed to get clock 'hdmiphy'\n");
2048 goto fail; 1834 goto fail;
2049 } 1835 }
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 2f4f72f07047..f08e2512c931 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -820,7 +820,6 @@ static void mixer_win_disable(void *ctx, int win)
820 820
821static int mixer_check_timing(void *ctx, struct fb_videomode *timing) 821static int mixer_check_timing(void *ctx, struct fb_videomode *timing)
822{ 822{
823 struct mixer_context *mixer_ctx = ctx;
824 u32 w, h; 823 u32 w, h;
825 824
826 w = timing->xres; 825 w = timing->xres;
@@ -831,9 +830,6 @@ static int mixer_check_timing(void *ctx, struct fb_videomode *timing)
831 timing->refresh, (timing->vmode & 830 timing->refresh, (timing->vmode &
832 FB_VMODE_INTERLACED) ? true : false); 831 FB_VMODE_INTERLACED) ? true : false);
833 832
834 if (mixer_ctx->mxr_ver == MXR_VER_0_0_0_16)
835 return 0;
836
837 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) || 833 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
838 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) || 834 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
839 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080)) 835 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
@@ -1047,13 +1043,13 @@ static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
1047 spin_lock_init(&mixer_res->reg_slock); 1043 spin_lock_init(&mixer_res->reg_slock);
1048 1044
1049 mixer_res->mixer = devm_clk_get(dev, "mixer"); 1045 mixer_res->mixer = devm_clk_get(dev, "mixer");
1050 if (IS_ERR_OR_NULL(mixer_res->mixer)) { 1046 if (IS_ERR(mixer_res->mixer)) {
1051 dev_err(dev, "failed to get clock 'mixer'\n"); 1047 dev_err(dev, "failed to get clock 'mixer'\n");
1052 return -ENODEV; 1048 return -ENODEV;
1053 } 1049 }
1054 1050
1055 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi"); 1051 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
1056 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) { 1052 if (IS_ERR(mixer_res->sclk_hdmi)) {
1057 dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); 1053 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
1058 return -ENODEV; 1054 return -ENODEV;
1059 } 1055 }
@@ -1096,17 +1092,17 @@ static int vp_resources_init(struct exynos_drm_hdmi_context *ctx,
1096 struct resource *res; 1092 struct resource *res;
1097 1093
1098 mixer_res->vp = devm_clk_get(dev, "vp"); 1094 mixer_res->vp = devm_clk_get(dev, "vp");
1099 if (IS_ERR_OR_NULL(mixer_res->vp)) { 1095 if (IS_ERR(mixer_res->vp)) {
1100 dev_err(dev, "failed to get clock 'vp'\n"); 1096 dev_err(dev, "failed to get clock 'vp'\n");
1101 return -ENODEV; 1097 return -ENODEV;
1102 } 1098 }
1103 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer"); 1099 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
1104 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) { 1100 if (IS_ERR(mixer_res->sclk_mixer)) {
1105 dev_err(dev, "failed to get clock 'sclk_mixer'\n"); 1101 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1106 return -ENODEV; 1102 return -ENODEV;
1107 } 1103 }
1108 mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac"); 1104 mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
1109 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) { 1105 if (IS_ERR(mixer_res->sclk_dac)) {
1110 dev_err(dev, "failed to get clock 'sclk_dac'\n"); 1106 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1111 return -ENODEV; 1107 return -ENODEV;
1112 } 1108 }