Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/sun4i: hdmi: add support for ddc-i2c-bus property

Sometimes it is desirabled to use a separate i2c controller for ddc
access. This adds support for the ddc-i2c-bus property of the
hdmi-connector node, using the specified controller if provided.

Signed-off-by: Mans Rullgard <mans@mansr.com>
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190328130249.19356-1-mans@mansr.com

authored by

Mans Rullgard and committed by
Maxime Ripard
088aed8b df61c776

+38 -3
+1
drivers/gpu/drm/sun4i/sun4i_hdmi.h
··· 269 269 struct clk *tmds_clk; 270 270 271 271 struct i2c_adapter *i2c; 272 + struct i2c_adapter *ddc_i2c; 272 273 273 274 /* Regmap fields for I2C adapter */ 274 275 struct regmap_field *field_ddc_en;
+37 -3
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
··· 217 217 struct edid *edid; 218 218 int ret; 219 219 220 - edid = drm_get_edid(connector, hdmi->i2c); 220 + edid = drm_get_edid(connector, hdmi->ddc_i2c ?: hdmi->i2c); 221 221 if (!edid) 222 222 return 0; 223 223 ··· 231 231 kfree(edid); 232 232 233 233 return ret; 234 + } 235 + 236 + static struct i2c_adapter *sun4i_hdmi_get_ddc(struct device *dev) 237 + { 238 + struct device_node *phandle, *remote; 239 + struct i2c_adapter *ddc; 240 + 241 + remote = of_graph_get_remote_node(dev->of_node, 1, -1); 242 + if (!remote) 243 + return ERR_PTR(-EINVAL); 244 + 245 + phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0); 246 + of_node_put(remote); 247 + if (!phandle) 248 + return ERR_PTR(-ENODEV); 249 + 250 + ddc = of_get_i2c_adapter_by_node(phandle); 251 + of_node_put(phandle); 252 + if (!ddc) 253 + return ERR_PTR(-EPROBE_DEFER); 254 + 255 + return ddc; 234 256 } 235 257 236 258 static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = { ··· 602 580 goto err_disable_mod_clk; 603 581 } 604 582 583 + hdmi->ddc_i2c = sun4i_hdmi_get_ddc(dev); 584 + if (IS_ERR(hdmi->ddc_i2c)) { 585 + ret = PTR_ERR(hdmi->ddc_i2c); 586 + if (ret == -ENODEV) 587 + hdmi->ddc_i2c = NULL; 588 + else 589 + goto err_del_i2c_adapter; 590 + } 591 + 605 592 drm_encoder_helper_add(&hdmi->encoder, 606 593 &sun4i_hdmi_helper_funcs); 607 594 ret = drm_encoder_init(drm, ··· 620 589 NULL); 621 590 if (ret) { 622 591 dev_err(dev, "Couldn't initialise the HDMI encoder\n"); 623 - goto err_del_i2c_adapter; 592 + goto err_put_ddc_i2c; 624 593 } 625 594 626 595 hdmi->encoder.possible_crtcs = drm_of_find_possible_crtcs(drm, 627 596 dev->of_node); 628 597 if (!hdmi->encoder.possible_crtcs) { 629 598 ret = -EPROBE_DEFER; 630 - goto err_del_i2c_adapter; 599 + goto err_put_ddc_i2c; 631 600 } 632 601 633 602 #ifdef CONFIG_DRM_SUN4I_HDMI_CEC ··· 666 635 err_cleanup_connector: 667 636 cec_delete_adapter(hdmi->cec_adap); 668 637 drm_encoder_cleanup(&hdmi->encoder); 638 + err_put_ddc_i2c: 639 + i2c_put_adapter(hdmi->ddc_i2c); 669 640 err_del_i2c_adapter: 670 641 i2c_del_adapter(hdmi->i2c); 671 642 err_disable_mod_clk: ··· 688 655 drm_connector_cleanup(&hdmi->connector); 689 656 drm_encoder_cleanup(&hdmi->encoder); 690 657 i2c_del_adapter(hdmi->i2c); 658 + i2c_put_adapter(hdmi->ddc_i2c); 691 659 clk_disable_unprepare(hdmi->mod_clk); 692 660 clk_disable_unprepare(hdmi->bus_clk); 693 661 }