aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2014-11-04 13:33:14 -0500
committerRob Clark <robdclark@gmail.com>2014-11-16 14:22:42 -0500
commit067fef372c7356f64e4d307218df0fae49f9c88e (patch)
tree208fe0b1e8dca420a2ae9849a54b91f907e5e4ba /drivers/gpu/drm/msm
parentbc00ae02e4a0b0d34a03bb25a8285b80e4f628c4 (diff)
drm/msm/hdmi: refactor bind/init
Split up hdmi_init() into hdmi_init() (done at hdmi sub-device bind/probe time) and hdmi_modeset_init() done from master driver's modeset_init(). Anything that can fail due to dependencies on other drivers which may be missing or not probed yet should go in hdmi_init(), so that devm error/cleanup paths work properly. Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm')
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c99
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c13
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c3
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c11
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h2
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h10
7 files changed, 85 insertions, 55 deletions
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 9d00dcba6959..90077619029d 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -68,24 +68,17 @@ void hdmi_destroy(struct kref *kref)
68 platform_set_drvdata(hdmi->pdev, NULL); 68 platform_set_drvdata(hdmi->pdev, NULL);
69} 69}
70 70
71/* initialize connector */ 71/* construct hdmi at bind/probe time, grab all the resources. If
72struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) 72 * we are to EPROBE_DEFER we want to do it here, rather than later
73 * at modeset_init() time
74 */
75static struct hdmi *hdmi_init(struct platform_device *pdev)
73{ 76{
77 struct hdmi_platform_config *config = pdev->dev.platform_data;
74 struct hdmi *hdmi = NULL; 78 struct hdmi *hdmi = NULL;
75 struct msm_drm_private *priv = dev->dev_private;
76 struct platform_device *pdev = priv->hdmi_pdev;
77 struct hdmi_platform_config *config;
78 int i, ret; 79 int i, ret;
79 80
80 if (!pdev) { 81 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
81 dev_err(dev->dev, "no hdmi device\n");
82 ret = -ENXIO;
83 goto fail;
84 }
85
86 config = pdev->dev.platform_data;
87
88 hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
89 if (!hdmi) { 82 if (!hdmi) {
90 ret = -ENOMEM; 83 ret = -ENOMEM;
91 goto fail; 84 goto fail;
@@ -93,12 +86,8 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
93 86
94 kref_init(&hdmi->refcount); 87 kref_init(&hdmi->refcount);
95 88
96 hdmi->dev = dev;
97 hdmi->pdev = pdev; 89 hdmi->pdev = pdev;
98 hdmi->config = config; 90 hdmi->config = config;
99 hdmi->encoder = encoder;
100
101 hdmi_audio_infoframe_init(&hdmi->audio.infoframe);
102 91
103 /* not sure about which phy maps to which msm.. probably I miss some */ 92 /* not sure about which phy maps to which msm.. probably I miss some */
104 if (config->phy_init) 93 if (config->phy_init)
@@ -108,7 +97,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
108 97
109 if (IS_ERR(hdmi->phy)) { 98 if (IS_ERR(hdmi->phy)) {
110 ret = PTR_ERR(hdmi->phy); 99 ret = PTR_ERR(hdmi->phy);
111 dev_err(dev->dev, "failed to load phy: %d\n", ret); 100 dev_err(&pdev->dev, "failed to load phy: %d\n", ret);
112 hdmi->phy = NULL; 101 hdmi->phy = NULL;
113 goto fail; 102 goto fail;
114 } 103 }
@@ -127,7 +116,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
127 config->hpd_reg_names[i]); 116 config->hpd_reg_names[i]);
128 if (IS_ERR(reg)) { 117 if (IS_ERR(reg)) {
129 ret = PTR_ERR(reg); 118 ret = PTR_ERR(reg);
130 dev_err(dev->dev, "failed to get hpd regulator: %s (%d)\n", 119 dev_err(&pdev->dev, "failed to get hpd regulator: %s (%d)\n",
131 config->hpd_reg_names[i], ret); 120 config->hpd_reg_names[i], ret);
132 goto fail; 121 goto fail;
133 } 122 }
@@ -143,7 +132,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
143 config->pwr_reg_names[i]); 132 config->pwr_reg_names[i]);
144 if (IS_ERR(reg)) { 133 if (IS_ERR(reg)) {
145 ret = PTR_ERR(reg); 134 ret = PTR_ERR(reg);
146 dev_err(dev->dev, "failed to get pwr regulator: %s (%d)\n", 135 dev_err(&pdev->dev, "failed to get pwr regulator: %s (%d)\n",
147 config->pwr_reg_names[i], ret); 136 config->pwr_reg_names[i], ret);
148 goto fail; 137 goto fail;
149 } 138 }
@@ -158,7 +147,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
158 clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]); 147 clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]);
159 if (IS_ERR(clk)) { 148 if (IS_ERR(clk)) {
160 ret = PTR_ERR(clk); 149 ret = PTR_ERR(clk);
161 dev_err(dev->dev, "failed to get hpd clk: %s (%d)\n", 150 dev_err(&pdev->dev, "failed to get hpd clk: %s (%d)\n",
162 config->hpd_clk_names[i], ret); 151 config->hpd_clk_names[i], ret);
163 goto fail; 152 goto fail;
164 } 153 }
@@ -173,7 +162,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
173 clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]); 162 clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]);
174 if (IS_ERR(clk)) { 163 if (IS_ERR(clk)) {
175 ret = PTR_ERR(clk); 164 ret = PTR_ERR(clk);
176 dev_err(dev->dev, "failed to get pwr clk: %s (%d)\n", 165 dev_err(&pdev->dev, "failed to get pwr clk: %s (%d)\n",
177 config->pwr_clk_names[i], ret); 166 config->pwr_clk_names[i], ret);
178 goto fail; 167 goto fail;
179 } 168 }
@@ -184,11 +173,41 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
184 hdmi->i2c = hdmi_i2c_init(hdmi); 173 hdmi->i2c = hdmi_i2c_init(hdmi);
185 if (IS_ERR(hdmi->i2c)) { 174 if (IS_ERR(hdmi->i2c)) {
186 ret = PTR_ERR(hdmi->i2c); 175 ret = PTR_ERR(hdmi->i2c);
187 dev_err(dev->dev, "failed to get i2c: %d\n", ret); 176 dev_err(&pdev->dev, "failed to get i2c: %d\n", ret);
188 hdmi->i2c = NULL; 177 hdmi->i2c = NULL;
189 goto fail; 178 goto fail;
190 } 179 }
191 180
181 return hdmi;
182
183fail:
184 if (hdmi)
185 hdmi_destroy(&hdmi->refcount);
186
187 return ERR_PTR(ret);
188}
189
190/* Second part of initialization, the drm/kms level modeset_init,
191 * constructs/initializes mode objects, etc, is called from master
192 * driver (not hdmi sub-device's probe/bind!)
193 *
194 * Any resource (regulator/clk/etc) which could be missing at boot
195 * should be handled in hdmi_init() so that failure happens from
196 * hdmi sub-device's probe.
197 */
198int hdmi_modeset_init(struct hdmi *hdmi,
199 struct drm_device *dev, struct drm_encoder *encoder)
200{
201 struct msm_drm_private *priv = dev->dev_private;
202 struct platform_device *pdev = hdmi->pdev;
203 struct hdmi_platform_config *config = pdev->dev.platform_data;
204 int ret;
205
206 hdmi->dev = dev;
207 hdmi->encoder = encoder;
208
209 hdmi_audio_infoframe_init(&hdmi->audio.infoframe);
210
192 hdmi->bridge = hdmi_bridge_init(hdmi); 211 hdmi->bridge = hdmi_bridge_init(hdmi);
193 if (IS_ERR(hdmi->bridge)) { 212 if (IS_ERR(hdmi->bridge)) {
194 ret = PTR_ERR(hdmi->bridge); 213 ret = PTR_ERR(hdmi->bridge);
@@ -230,19 +249,20 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
230 249
231 platform_set_drvdata(pdev, hdmi); 250 platform_set_drvdata(pdev, hdmi);
232 251
233 return hdmi; 252 return 0;
234 253
235fail: 254fail:
236 if (hdmi) { 255 /* bridge/connector are normally destroyed by drm: */
237 /* bridge/connector are normally destroyed by drm: */ 256 if (hdmi->bridge) {
238 if (hdmi->bridge) 257 hdmi->bridge->funcs->destroy(hdmi->bridge);
239 hdmi->bridge->funcs->destroy(hdmi->bridge); 258 hdmi->bridge = NULL;
240 if (hdmi->connector) 259 }
241 hdmi->connector->funcs->destroy(hdmi->connector); 260 if (hdmi->connector) {
242 hdmi_destroy(&hdmi->refcount); 261 hdmi->connector->funcs->destroy(hdmi->connector);
262 hdmi->connector = NULL;
243 } 263 }
244 264
245 return ERR_PTR(ret); 265 return ret;
246} 266}
247 267
248/* 268/*
@@ -251,11 +271,10 @@ fail:
251 271
252#include <linux/of_gpio.h> 272#include <linux/of_gpio.h>
253 273
254static void set_hdmi_pdev(struct drm_device *dev, 274static void set_hdmi(struct drm_device *dev, struct hdmi *hdmi)
255 struct platform_device *pdev)
256{ 275{
257 struct msm_drm_private *priv = dev->dev_private; 276 struct msm_drm_private *priv = dev->dev_private;
258 priv->hdmi_pdev = pdev; 277 priv->hdmi = hdmi;
259} 278}
260 279
261#ifdef CONFIG_OF 280#ifdef CONFIG_OF
@@ -279,6 +298,7 @@ static int get_gpio(struct device *dev, struct device_node *of_node, const char
279static int hdmi_bind(struct device *dev, struct device *master, void *data) 298static int hdmi_bind(struct device *dev, struct device *master, void *data)
280{ 299{
281 static struct hdmi_platform_config config = {}; 300 static struct hdmi_platform_config config = {};
301 struct hdmi *hdmi;
282#ifdef CONFIG_OF 302#ifdef CONFIG_OF
283 struct device_node *of_node = dev->of_node; 303 struct device_node *of_node = dev->of_node;
284 304
@@ -369,14 +389,17 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
369 } 389 }
370#endif 390#endif
371 dev->platform_data = &config; 391 dev->platform_data = &config;
372 set_hdmi_pdev(dev_get_drvdata(master), to_platform_device(dev)); 392 hdmi = hdmi_init(to_platform_device(dev));
393 if (IS_ERR(hdmi))
394 return PTR_ERR(hdmi);
395 set_hdmi(dev_get_drvdata(master), hdmi);
373 return 0; 396 return 0;
374} 397}
375 398
376static void hdmi_unbind(struct device *dev, struct device *master, 399static void hdmi_unbind(struct device *dev, struct device *master,
377 void *data) 400 void *data)
378{ 401{
379 set_hdmi_pdev(dev_get_drvdata(master), NULL); 402 set_hdmi(dev_get_drvdata(master), NULL);
380} 403}
381 404
382static const struct component_ops hdmi_ops = { 405static const struct component_ops hdmi_ops = {
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
index f408b69486a8..eeed006eed13 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
@@ -510,7 +510,7 @@ struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi)
510 510
511#ifdef CONFIG_COMMON_CLK 511#ifdef CONFIG_COMMON_CLK
512 phy_8960->pll_hw.init = &pll_init; 512 phy_8960->pll_hw.init = &pll_init;
513 phy_8960->pll = devm_clk_register(hdmi->dev->dev, &phy_8960->pll_hw); 513 phy_8960->pll = devm_clk_register(&hdmi->pdev->dev, &phy_8960->pll_hw);
514 if (IS_ERR(phy_8960->pll)) { 514 if (IS_ERR(phy_8960->pll)) {
515 ret = PTR_ERR(phy_8960->pll); 515 ret = PTR_ERR(phy_8960->pll);
516 phy_8960->pll = NULL; 516 phy_8960->pll = NULL;
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index ac204720429e..a62109e4ae0d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -228,7 +228,6 @@ static int modeset_init(struct mdp4_kms *mdp4_kms)
228 struct drm_encoder *encoder; 228 struct drm_encoder *encoder;
229 struct drm_connector *connector; 229 struct drm_connector *connector;
230 struct drm_panel *panel; 230 struct drm_panel *panel;
231 struct hdmi *hdmi;
232 int ret; 231 int ret;
233 232
234 /* construct non-private planes: */ 233 /* construct non-private planes: */
@@ -326,11 +325,13 @@ static int modeset_init(struct mdp4_kms *mdp4_kms)
326 priv->crtcs[priv->num_crtcs++] = crtc; 325 priv->crtcs[priv->num_crtcs++] = crtc;
327 priv->encoders[priv->num_encoders++] = encoder; 326 priv->encoders[priv->num_encoders++] = encoder;
328 327
329 hdmi = hdmi_init(dev, encoder); 328 if (priv->hdmi) {
330 if (IS_ERR(hdmi)) { 329 /* Construct bridge/connector for HDMI: */
331 ret = PTR_ERR(hdmi); 330 ret = hdmi_modeset_init(priv->hdmi, dev, encoder);
332 dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret); 331 if (ret) {
333 goto fail; 332 dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret);
333 goto fail;
334 }
334 } 335 }
335 336
336 return 0; 337 return 0;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
index f2b985bc2adf..812c59bbaf7f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
@@ -82,6 +82,7 @@ irqreturn_t mdp5_irq(struct msm_kms *kms)
82{ 82{
83 struct mdp_kms *mdp_kms = to_mdp_kms(kms); 83 struct mdp_kms *mdp_kms = to_mdp_kms(kms);
84 struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms); 84 struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
85 struct msm_drm_private *priv = mdp5_kms->dev->dev_private;
85 uint32_t intr; 86 uint32_t intr;
86 87
87 intr = mdp5_read(mdp5_kms, REG_MDP5_HW_INTR_STATUS); 88 intr = mdp5_read(mdp5_kms, REG_MDP5_HW_INTR_STATUS);
@@ -92,7 +93,7 @@ irqreturn_t mdp5_irq(struct msm_kms *kms)
92 mdp5_irq_mdp(mdp_kms); 93 mdp5_irq_mdp(mdp_kms);
93 94
94 if (intr & MDP5_HW_INTR_STATUS_INTR_HDMI) 95 if (intr & MDP5_HW_INTR_STATUS_INTR_HDMI)
95 hdmi_irq(0, mdp5_kms->hdmi); 96 hdmi_irq(0, priv->hdmi);
96 97
97 return IRQ_HANDLED; 98 return IRQ_HANDLED;
98} 99}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 31a2c6331a1d..ce0308124a72 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -324,11 +324,12 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
324 priv->encoders[priv->num_encoders++] = encoder; 324 priv->encoders[priv->num_encoders++] = encoder;
325 325
326 /* Construct bridge/connector for HDMI: */ 326 /* Construct bridge/connector for HDMI: */
327 mdp5_kms->hdmi = hdmi_init(dev, encoder); 327 if (priv->hdmi) {
328 if (IS_ERR(mdp5_kms->hdmi)) { 328 ret = hdmi_modeset_init(priv->hdmi, dev, encoder);
329 ret = PTR_ERR(mdp5_kms->hdmi); 329 if (ret) {
330 dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret); 330 dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret);
331 goto fail; 331 goto fail;
332 }
332 } 333 }
333 334
334 return 0; 335 return 0;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 5bf340dd0f00..c91101d5ac0f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -71,8 +71,6 @@ struct mdp5_kms {
71 struct clk *lut_clk; 71 struct clk *lut_clk;
72 struct clk *vsync_clk; 72 struct clk *vsync_clk;
73 73
74 struct hdmi *hdmi;
75
76 struct mdp_irq error_handler; 74 struct mdp_irq error_handler;
77}; 75};
78#define to_mdp5_kms(x) container_of(x, struct mdp5_kms, base) 76#define to_mdp5_kms(x) container_of(x, struct mdp5_kms, base)
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 67f9d0a2332c..a0398b72ea21 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -75,7 +75,12 @@ struct msm_drm_private {
75 struct msm_kms *kms; 75 struct msm_kms *kms;
76 76
77 /* subordinate devices, if present: */ 77 /* subordinate devices, if present: */
78 struct platform_device *hdmi_pdev, *gpu_pdev; 78 struct platform_device *gpu_pdev;
79
80 /* possibly this should be in the kms component, but it is
81 * shared by both mdp4 and mdp5..
82 */
83 struct hdmi *hdmi;
79 84
80 /* when we have more than one 'msm_gpu' these need to be an array: */ 85 /* when we have more than one 'msm_gpu' these need to be an array: */
81 struct msm_gpu *gpu; 86 struct msm_gpu *gpu;
@@ -202,7 +207,8 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
202struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev); 207struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev);
203 208
204struct hdmi; 209struct hdmi;
205struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder); 210int hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev,
211 struct drm_encoder *encoder);
206irqreturn_t hdmi_irq(int irq, void *dev_id); 212irqreturn_t hdmi_irq(int irq, void *dev_id);
207void __init hdmi_register(void); 213void __init hdmi_register(void);
208void __exit hdmi_unregister(void); 214void __exit hdmi_unregister(void);