aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Yao <mark.yao@rock-chips.com>2016-04-19 22:41:42 -0400
committerMark Yao <mark.yao@rock-chips.com>2016-05-03 02:11:23 -0400
commit4e257d9eee23582e36637ce7ea6b14f6f56b1839 (patch)
treef0e468f54da21d6f0561ca5313d5d73fbc773d91
parent2743becb3338cf012dbe7b70c6c39bbac81cc101 (diff)
drm/rockchip: get rid of rockchip_drm_crtc_mode_config
We need to take care of the vop status when use rockchip_drm_crtc_mode_config, if vop is disabled, the function would failed, that is terrible. Save output_type and output_mode into rockchip_crtc_state, it's nice to make them into atomic. Signed-off-by: Mark Yao <mark.yao@rock-chips.com> Tested-by: John Keeping <john@metanate.com>
-rw-r--r--drivers/gpu/drm/rockchip/analogix_dp-rockchip.c48
-rw-r--r--drivers/gpu/drm/rockchip/dw-mipi-dsi.c38
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c17
-rw-r--r--drivers/gpu/drm/rockchip/inno_hdmi.c17
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.h10
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c75
6 files changed, 128 insertions, 77 deletions
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index a1d94d8d9443..7f6a55cae27a 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -114,27 +114,6 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder)
114 int ret; 114 int ret;
115 u32 val; 115 u32 val;
116 116
117 /*
118 * FIXME(Yakir): driver should configure the CRTC output video
119 * mode with the display information which indicated the monitor
120 * support colorimetry.
121 *
122 * But don't know why the CRTC driver seems could only output the
123 * RGBaaa rightly. For example, if connect the "innolux,n116bge"
124 * eDP screen, EDID would indicated that screen only accepted the
125 * 6bpc mode. But if I configure CRTC to RGB666 output, then eDP
126 * screen would show a blue picture (RGB888 show a green picture).
127 * But if I configure CTRC to RGBaaa, and eDP driver still keep
128 * RGB666 input video mode, then screen would works prefect.
129 */
130 ret = rockchip_drm_crtc_mode_config(encoder->crtc,
131 DRM_MODE_CONNECTOR_eDP,
132 ROCKCHIP_OUT_MODE_AAAA);
133 if (ret < 0) {
134 dev_err(dp->dev, "Could not set crtc mode config (%d)\n", ret);
135 return;
136 }
137
138 ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder); 117 ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
139 if (ret < 0) 118 if (ret < 0)
140 return; 119 return;
@@ -158,11 +137,38 @@ static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder)
158 /* do nothing */ 137 /* do nothing */
159} 138}
160 139
140static int
141rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
142 struct drm_crtc_state *crtc_state,
143 struct drm_connector_state *conn_state)
144{
145 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
146
147 /*
148 * FIXME(Yakir): driver should configure the CRTC output video
149 * mode with the display information which indicated the monitor
150 * support colorimetry.
151 *
152 * But don't know why the CRTC driver seems could only output the
153 * RGBaaa rightly. For example, if connect the "innolux,n116bge"
154 * eDP screen, EDID would indicated that screen only accepted the
155 * 6bpc mode. But if I configure CRTC to RGB666 output, then eDP
156 * screen would show a blue picture (RGB888 show a green picture).
157 * But if I configure CTRC to RGBaaa, and eDP driver still keep
158 * RGB666 input video mode, then screen would works prefect.
159 */
160 s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
161 s->output_type = DRM_MODE_CONNECTOR_eDP;
162
163 return 0;
164}
165
161static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = { 166static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = {
162 .mode_fixup = rockchip_dp_drm_encoder_mode_fixup, 167 .mode_fixup = rockchip_dp_drm_encoder_mode_fixup,
163 .mode_set = rockchip_dp_drm_encoder_mode_set, 168 .mode_set = rockchip_dp_drm_encoder_mode_set,
164 .enable = rockchip_dp_drm_encoder_enable, 169 .enable = rockchip_dp_drm_encoder_enable,
165 .disable = rockchip_dp_drm_encoder_nop, 170 .disable = rockchip_dp_drm_encoder_nop,
171 .atomic_check = rockchip_dp_drm_encoder_atomic_check,
166}; 172};
167 173
168static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder) 174static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 7975158064e8..dedc65b40f36 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -879,7 +879,6 @@ static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder)
879{ 879{
880 struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder); 880 struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder);
881 int mux = drm_of_encoder_active_endpoint_id(dsi->dev->of_node, encoder); 881 int mux = drm_of_encoder_active_endpoint_id(dsi->dev->of_node, encoder);
882 u32 interface_pix_fmt;
883 u32 val; 882 u32 val;
884 883
885 if (clk_prepare_enable(dsi->pclk)) { 884 if (clk_prepare_enable(dsi->pclk)) {
@@ -895,31 +894,41 @@ static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder)
895 894
896 clk_disable_unprepare(dsi->pclk); 895 clk_disable_unprepare(dsi->pclk);
897 896
897 if (mux)
898 val = DSI0_SEL_VOP_LIT | (DSI0_SEL_VOP_LIT << 16);
899 else
900 val = DSI0_SEL_VOP_LIT << 16;
901
902 regmap_write(dsi->grf_regmap, GRF_SOC_CON6, val);
903 dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
904}
905
906static int
907dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder,
908 struct drm_crtc_state *crtc_state,
909 struct drm_connector_state *conn_state)
910{
911 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
912 struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder);
913
898 switch (dsi->format) { 914 switch (dsi->format) {
899 case MIPI_DSI_FMT_RGB888: 915 case MIPI_DSI_FMT_RGB888:
900 interface_pix_fmt = ROCKCHIP_OUT_MODE_P888; 916 s->output_mode = ROCKCHIP_OUT_MODE_P888;
901 break; 917 break;
902 case MIPI_DSI_FMT_RGB666: 918 case MIPI_DSI_FMT_RGB666:
903 interface_pix_fmt = ROCKCHIP_OUT_MODE_P666; 919 s->output_mode = ROCKCHIP_OUT_MODE_P666;
904 break; 920 break;
905 case MIPI_DSI_FMT_RGB565: 921 case MIPI_DSI_FMT_RGB565:
906 interface_pix_fmt = ROCKCHIP_OUT_MODE_P565; 922 s->output_mode = ROCKCHIP_OUT_MODE_P565;
907 break; 923 break;
908 default: 924 default:
909 WARN_ON(1); 925 WARN_ON(1);
910 return; 926 return -EINVAL;
911 } 927 }
912 928
913 rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_DSI, 929 s->output_type = DRM_MODE_CONNECTOR_DSI;
914 interface_pix_fmt);
915 930
916 if (mux) 931 return 0;
917 val = DSI0_SEL_VOP_LIT | (DSI0_SEL_VOP_LIT << 16);
918 else
919 val = DSI0_SEL_VOP_LIT << 16;
920
921 regmap_write(dsi->grf_regmap, GRF_SOC_CON6, val);
922 dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
923} 932}
924 933
925static struct drm_encoder_helper_funcs 934static struct drm_encoder_helper_funcs
@@ -927,6 +936,7 @@ dw_mipi_dsi_encoder_helper_funcs = {
927 .commit = dw_mipi_dsi_encoder_commit, 936 .commit = dw_mipi_dsi_encoder_commit,
928 .mode_set = dw_mipi_dsi_encoder_mode_set, 937 .mode_set = dw_mipi_dsi_encoder_mode_set,
929 .disable = dw_mipi_dsi_encoder_disable, 938 .disable = dw_mipi_dsi_encoder_disable,
939 .atomic_check = dw_mipi_dsi_encoder_atomic_check,
930}; 940};
931 941
932static struct drm_encoder_funcs dw_mipi_dsi_encoder_funcs = { 942static struct drm_encoder_funcs dw_mipi_dsi_encoder_funcs = {
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index d5cfef75fc80..801110f65a63 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -201,9 +201,6 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
201 u32 val; 201 u32 val;
202 int mux; 202 int mux;
203 203
204 rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
205 ROCKCHIP_OUT_MODE_AAAA);
206
207 mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); 204 mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder);
208 if (mux) 205 if (mux)
209 val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16); 206 val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16);
@@ -215,11 +212,25 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
215 (mux) ? "LIT" : "BIG"); 212 (mux) ? "LIT" : "BIG");
216} 213}
217 214
215static int
216dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
217 struct drm_crtc_state *crtc_state,
218 struct drm_connector_state *conn_state)
219{
220 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
221
222 s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
223 s->output_type = DRM_MODE_CONNECTOR_HDMIA;
224
225 return 0;
226}
227
218static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { 228static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
219 .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, 229 .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup,
220 .mode_set = dw_hdmi_rockchip_encoder_mode_set, 230 .mode_set = dw_hdmi_rockchip_encoder_mode_set,
221 .enable = dw_hdmi_rockchip_encoder_enable, 231 .enable = dw_hdmi_rockchip_encoder_enable,
222 .disable = dw_hdmi_rockchip_encoder_disable, 232 .disable = dw_hdmi_rockchip_encoder_disable,
233 .atomic_check = dw_hdmi_rockchip_encoder_atomic_check,
223}; 234};
224 235
225static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = { 236static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = {
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
index f25244199626..f8b4feb60b25 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -500,9 +500,6 @@ static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
500{ 500{
501 struct inno_hdmi *hdmi = to_inno_hdmi(encoder); 501 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
502 502
503 rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
504 ROCKCHIP_OUT_MODE_P888);
505
506 inno_hdmi_set_pwr_mode(hdmi, NORMAL); 503 inno_hdmi_set_pwr_mode(hdmi, NORMAL);
507} 504}
508 505
@@ -520,11 +517,25 @@ static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
520 return true; 517 return true;
521} 518}
522 519
520static int
521inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
522 struct drm_crtc_state *crtc_state,
523 struct drm_connector_state *conn_state)
524{
525 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
526
527 s->output_mode = ROCKCHIP_OUT_MODE_P888;
528 s->output_type = DRM_MODE_CONNECTOR_HDMIA;
529
530 return 0;
531}
532
523static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = { 533static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
524 .enable = inno_hdmi_encoder_enable, 534 .enable = inno_hdmi_encoder_enable,
525 .disable = inno_hdmi_encoder_disable, 535 .disable = inno_hdmi_encoder_disable,
526 .mode_fixup = inno_hdmi_encoder_mode_fixup, 536 .mode_fixup = inno_hdmi_encoder_mode_fixup,
527 .mode_set = inno_hdmi_encoder_mode_set, 537 .mode_set = inno_hdmi_encoder_mode_set,
538 .atomic_check = inno_hdmi_encoder_atomic_check,
528}; 539};
529 540
530static struct drm_encoder_funcs inno_hdmi_encoder_funcs = { 541static struct drm_encoder_funcs inno_hdmi_encoder_funcs = {
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 00d17d71aa4c..56f43a364c7f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -50,6 +50,14 @@ struct rockchip_atomic_commit {
50 struct mutex lock; 50 struct mutex lock;
51}; 51};
52 52
53struct rockchip_crtc_state {
54 struct drm_crtc_state base;
55 int output_type;
56 int output_mode;
57};
58#define to_rockchip_crtc_state(s) \
59 container_of(s, struct rockchip_crtc_state, base)
60
53/* 61/*
54 * Rockchip drm private structure. 62 * Rockchip drm private structure.
55 * 63 *
@@ -68,8 +76,6 @@ void rockchip_drm_atomic_work(struct work_struct *work);
68int rockchip_register_crtc_funcs(struct drm_crtc *crtc, 76int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
69 const struct rockchip_crtc_funcs *crtc_funcs); 77 const struct rockchip_crtc_funcs *crtc_funcs);
70void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc); 78void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
71int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, int connector_type,
72 int out_mode);
73int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, 79int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
74 struct device *dev); 80 struct device *dev);
75void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, 81void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index a619f120f801..28596e72df2b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -818,38 +818,6 @@ static const struct drm_plane_funcs vop_plane_funcs = {
818 .atomic_destroy_state = vop_atomic_plane_destroy_state, 818 .atomic_destroy_state = vop_atomic_plane_destroy_state,
819}; 819};
820 820
821int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc,
822 int connector_type,
823 int out_mode)
824{
825 struct vop *vop = to_vop(crtc);
826
827 if (WARN_ON(!vop->is_enabled))
828 return -EINVAL;
829
830 switch (connector_type) {
831 case DRM_MODE_CONNECTOR_LVDS:
832 VOP_CTRL_SET(vop, rgb_en, 1);
833 break;
834 case DRM_MODE_CONNECTOR_eDP:
835 VOP_CTRL_SET(vop, edp_en, 1);
836 break;
837 case DRM_MODE_CONNECTOR_HDMIA:
838 VOP_CTRL_SET(vop, hdmi_en, 1);
839 break;
840 case DRM_MODE_CONNECTOR_DSI:
841 VOP_CTRL_SET(vop, mipi_en, 1);
842 break;
843 default:
844 DRM_ERROR("unsupport connector_type[%d]\n", connector_type);
845 return -EINVAL;
846 };
847 VOP_CTRL_SET(vop, out_mode, out_mode);
848
849 return 0;
850}
851EXPORT_SYMBOL_GPL(rockchip_drm_crtc_mode_config);
852
853static int vop_crtc_enable_vblank(struct drm_crtc *crtc) 821static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
854{ 822{
855 struct vop *vop = to_vop(crtc); 823 struct vop *vop = to_vop(crtc);
@@ -931,6 +899,7 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
931static void vop_crtc_enable(struct drm_crtc *crtc) 899static void vop_crtc_enable(struct drm_crtc *crtc)
932{ 900{
933 struct vop *vop = to_vop(crtc); 901 struct vop *vop = to_vop(crtc);
902 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
934 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; 903 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
935 u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start; 904 u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
936 u16 hdisplay = adjusted_mode->hdisplay; 905 u16 hdisplay = adjusted_mode->hdisplay;
@@ -985,6 +954,23 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
985 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1; 954 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
986 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1); 955 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
987 VOP_CTRL_SET(vop, pin_pol, val); 956 VOP_CTRL_SET(vop, pin_pol, val);
957 switch (s->output_type) {
958 case DRM_MODE_CONNECTOR_LVDS:
959 VOP_CTRL_SET(vop, rgb_en, 1);
960 break;
961 case DRM_MODE_CONNECTOR_eDP:
962 VOP_CTRL_SET(vop, edp_en, 1);
963 break;
964 case DRM_MODE_CONNECTOR_HDMIA:
965 VOP_CTRL_SET(vop, hdmi_en, 1);
966 break;
967 case DRM_MODE_CONNECTOR_DSI:
968 VOP_CTRL_SET(vop, mipi_en, 1);
969 break;
970 default:
971 DRM_ERROR("unsupport connector_type[%d]\n", s->output_type);
972 }
973 VOP_CTRL_SET(vop, out_mode, s->output_mode);
988 974
989 VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len); 975 VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len);
990 val = hact_st << 16; 976 val = hact_st << 16;
@@ -1044,13 +1030,34 @@ static void vop_crtc_destroy(struct drm_crtc *crtc)
1044 drm_crtc_cleanup(crtc); 1030 drm_crtc_cleanup(crtc);
1045} 1031}
1046 1032
1033static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc)
1034{
1035 struct rockchip_crtc_state *rockchip_state;
1036
1037 rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL);
1038 if (!rockchip_state)
1039 return NULL;
1040
1041 __drm_atomic_helper_crtc_duplicate_state(crtc, &rockchip_state->base);
1042 return &rockchip_state->base;
1043}
1044
1045static void vop_crtc_destroy_state(struct drm_crtc *crtc,
1046 struct drm_crtc_state *state)
1047{
1048 struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
1049
1050 __drm_atomic_helper_crtc_destroy_state(crtc, &s->base);
1051 kfree(s);
1052}
1053
1047static const struct drm_crtc_funcs vop_crtc_funcs = { 1054static const struct drm_crtc_funcs vop_crtc_funcs = {
1048 .set_config = drm_atomic_helper_set_config, 1055 .set_config = drm_atomic_helper_set_config,
1049 .page_flip = drm_atomic_helper_page_flip, 1056 .page_flip = drm_atomic_helper_page_flip,
1050 .destroy = vop_crtc_destroy, 1057 .destroy = vop_crtc_destroy,
1051 .reset = drm_atomic_helper_crtc_reset, 1058 .reset = drm_atomic_helper_crtc_reset,
1052 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 1059 .atomic_duplicate_state = vop_crtc_duplicate_state,
1053 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 1060 .atomic_destroy_state = vop_crtc_destroy_state,
1054}; 1061};
1055 1062
1056static bool vop_win_pending_is_complete(struct vop_win *vop_win) 1063static bool vop_win_pending_is_complete(struct vop_win *vop_win)