brintos

brintos / linux-shallow public Read only

0
0
Text · 18.8 KiB · 9b8747d Raw
862 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * HDMI interface DSS driver for TI's OMAP4 family of SoCs.4 *5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com/6 * Authors: Yong Zhi7 *	Mythri pk <mythripk@ti.com>8 */9 10#define DSS_SUBSYS_NAME "HDMI"11 12#include <linux/kernel.h>13#include <linux/module.h>14#include <linux/err.h>15#include <linux/io.h>16#include <linux/interrupt.h>17#include <linux/mutex.h>18#include <linux/delay.h>19#include <linux/string.h>20#include <linux/platform_device.h>21#include <linux/pm_runtime.h>22#include <linux/clk.h>23#include <linux/regulator/consumer.h>24#include <linux/component.h>25#include <linux/of.h>26#include <linux/of_graph.h>27#include <sound/omap-hdmi-audio.h>28#include <media/cec.h>29 30#include <drm/drm_atomic.h>31#include <drm/drm_atomic_state_helper.h>32#include <drm/drm_edid.h>33 34#include "omapdss.h"35#include "hdmi4_core.h"36#include "hdmi4_cec.h"37#include "dss.h"38#include "hdmi.h"39 40static int hdmi_runtime_get(struct omap_hdmi *hdmi)41{42	int r;43 44	DSSDBG("hdmi_runtime_get\n");45 46	r = pm_runtime_get_sync(&hdmi->pdev->dev);47	if (WARN_ON(r < 0)) {48		pm_runtime_put_noidle(&hdmi->pdev->dev);49		return r;50	}51	return 0;52}53 54static void hdmi_runtime_put(struct omap_hdmi *hdmi)55{56	int r;57 58	DSSDBG("hdmi_runtime_put\n");59 60	r = pm_runtime_put_sync(&hdmi->pdev->dev);61	WARN_ON(r < 0 && r != -ENOSYS);62}63 64static irqreturn_t hdmi_irq_handler(int irq, void *data)65{66	struct omap_hdmi *hdmi = data;67	struct hdmi_wp_data *wp = &hdmi->wp;68	u32 irqstatus;69 70	irqstatus = hdmi_wp_get_irqstatus(wp);71	hdmi_wp_set_irqstatus(wp, irqstatus);72 73	if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&74			irqstatus & HDMI_IRQ_LINK_DISCONNECT) {75		/*76		 * If we get both connect and disconnect interrupts at the same77		 * time, turn off the PHY, clear interrupts, and restart, which78		 * raises connect interrupt if a cable is connected, or nothing79		 * if cable is not connected.80		 */81		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);82 83		hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |84				HDMI_IRQ_LINK_DISCONNECT);85 86		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);87	} else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {88		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);89	} else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {90		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);91	}92	if (irqstatus & HDMI_IRQ_CORE) {93		u32 intr4 = hdmi_read_reg(hdmi->core.base, HDMI_CORE_SYS_INTR4);94 95		hdmi_write_reg(hdmi->core.base, HDMI_CORE_SYS_INTR4, intr4);96		if (intr4 & 8)97			hdmi4_cec_irq(&hdmi->core);98	}99 100	return IRQ_HANDLED;101}102 103static int hdmi_power_on_core(struct omap_hdmi *hdmi)104{105	int r;106 107	if (hdmi->core.core_pwr_cnt++)108		return 0;109 110	r = regulator_enable(hdmi->vdda_reg);111	if (r)112		goto err_reg_enable;113 114	r = hdmi_runtime_get(hdmi);115	if (r)116		goto err_runtime_get;117 118	hdmi4_core_powerdown_disable(&hdmi->core);119 120	/* Make selection of HDMI in DSS */121	dss_select_hdmi_venc_clk_source(hdmi->dss, DSS_HDMI_M_PCLK);122 123	hdmi->core_enabled = true;124 125	return 0;126 127err_runtime_get:128	regulator_disable(hdmi->vdda_reg);129err_reg_enable:130	hdmi->core.core_pwr_cnt--;131 132	return r;133}134 135static void hdmi_power_off_core(struct omap_hdmi *hdmi)136{137	if (--hdmi->core.core_pwr_cnt)138		return;139 140	hdmi->core_enabled = false;141 142	hdmi_runtime_put(hdmi);143	regulator_disable(hdmi->vdda_reg);144}145 146static int hdmi_power_on_full(struct omap_hdmi *hdmi)147{148	int r;149	const struct videomode *vm;150	struct hdmi_wp_data *wp = &hdmi->wp;151	struct dss_pll_clock_info hdmi_cinfo = { 0 };152	unsigned int pc;153 154	r = hdmi_power_on_core(hdmi);155	if (r)156		return r;157 158	/* disable and clear irqs */159	hdmi_wp_clear_irqenable(wp, ~HDMI_IRQ_CORE);160	hdmi_wp_set_irqstatus(wp, ~HDMI_IRQ_CORE);161 162	vm = &hdmi->cfg.vm;163 164	DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", vm->hactive,165	       vm->vactive);166 167	pc = vm->pixelclock;168	if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)169		pc *= 2;170 171	/* DSS_HDMI_TCLK is bitclk / 10 */172	pc *= 10;173 174	dss_pll_calc_b(&hdmi->pll.pll, clk_get_rate(hdmi->pll.pll.clkin),175		pc, &hdmi_cinfo);176 177	r = dss_pll_enable(&hdmi->pll.pll);178	if (r) {179		DSSERR("Failed to enable PLL\n");180		goto err_pll_enable;181	}182 183	r = dss_pll_set_config(&hdmi->pll.pll, &hdmi_cinfo);184	if (r) {185		DSSERR("Failed to configure PLL\n");186		goto err_pll_cfg;187	}188 189	r = hdmi_phy_configure(&hdmi->phy, hdmi_cinfo.clkdco,190		hdmi_cinfo.clkout[0]);191	if (r) {192		DSSDBG("Failed to configure PHY\n");193		goto err_phy_cfg;194	}195 196	r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);197	if (r)198		goto err_phy_pwr;199 200	hdmi4_configure(&hdmi->core, &hdmi->wp, &hdmi->cfg);201 202	r = dss_mgr_enable(&hdmi->output);203	if (r)204		goto err_mgr_enable;205 206	r = hdmi_wp_video_start(&hdmi->wp);207	if (r)208		goto err_vid_enable;209 210	hdmi_wp_set_irqenable(wp,211		HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);212 213	return 0;214 215err_vid_enable:216	dss_mgr_disable(&hdmi->output);217err_mgr_enable:218	hdmi_wp_set_phy_pwr(&hdmi->wp, HDMI_PHYPWRCMD_OFF);219err_phy_pwr:220err_phy_cfg:221err_pll_cfg:222	dss_pll_disable(&hdmi->pll.pll);223err_pll_enable:224	hdmi_power_off_core(hdmi);225	return -EIO;226}227 228static void hdmi_power_off_full(struct omap_hdmi *hdmi)229{230	hdmi_wp_clear_irqenable(&hdmi->wp, ~HDMI_IRQ_CORE);231 232	hdmi_wp_video_stop(&hdmi->wp);233 234	dss_mgr_disable(&hdmi->output);235 236	hdmi_wp_set_phy_pwr(&hdmi->wp, HDMI_PHYPWRCMD_OFF);237 238	dss_pll_disable(&hdmi->pll.pll);239 240	hdmi_power_off_core(hdmi);241}242 243static int hdmi_dump_regs(struct seq_file *s, void *p)244{245	struct omap_hdmi *hdmi = s->private;246 247	mutex_lock(&hdmi->lock);248 249	if (hdmi_runtime_get(hdmi)) {250		mutex_unlock(&hdmi->lock);251		return 0;252	}253 254	hdmi_wp_dump(&hdmi->wp, s);255	hdmi_pll_dump(&hdmi->pll, s);256	hdmi_phy_dump(&hdmi->phy, s);257	hdmi4_core_dump(&hdmi->core, s);258 259	hdmi_runtime_put(hdmi);260	mutex_unlock(&hdmi->lock);261	return 0;262}263 264static void hdmi_start_audio_stream(struct omap_hdmi *hd)265{266	hdmi_wp_audio_enable(&hd->wp, true);267	hdmi4_audio_start(&hd->core, &hd->wp);268}269 270static void hdmi_stop_audio_stream(struct omap_hdmi *hd)271{272	hdmi4_audio_stop(&hd->core, &hd->wp);273	hdmi_wp_audio_enable(&hd->wp, false);274}275 276int hdmi4_core_enable(struct hdmi_core_data *core)277{278	struct omap_hdmi *hdmi = container_of(core, struct omap_hdmi, core);279	int r = 0;280 281	DSSDBG("ENTER omapdss_hdmi4_core_enable\n");282 283	mutex_lock(&hdmi->lock);284 285	r = hdmi_power_on_core(hdmi);286	if (r) {287		DSSERR("failed to power on device\n");288		goto err0;289	}290 291	mutex_unlock(&hdmi->lock);292	return 0;293 294err0:295	mutex_unlock(&hdmi->lock);296	return r;297}298 299void hdmi4_core_disable(struct hdmi_core_data *core)300{301	struct omap_hdmi *hdmi = container_of(core, struct omap_hdmi, core);302 303	DSSDBG("Enter omapdss_hdmi4_core_disable\n");304 305	mutex_lock(&hdmi->lock);306 307	hdmi_power_off_core(hdmi);308 309	mutex_unlock(&hdmi->lock);310}311 312/* -----------------------------------------------------------------------------313 * DRM Bridge Operations314 */315 316static int hdmi4_bridge_attach(struct drm_bridge *bridge,317			       enum drm_bridge_attach_flags flags)318{319	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);320 321	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))322		return -EINVAL;323 324	return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge,325				 bridge, flags);326}327 328static void hdmi4_bridge_mode_set(struct drm_bridge *bridge,329				  const struct drm_display_mode *mode,330				  const struct drm_display_mode *adjusted_mode)331{332	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);333 334	mutex_lock(&hdmi->lock);335 336	drm_display_mode_to_videomode(adjusted_mode, &hdmi->cfg.vm);337 338	dispc_set_tv_pclk(hdmi->dss->dispc, adjusted_mode->clock * 1000);339 340	mutex_unlock(&hdmi->lock);341}342 343static void hdmi4_bridge_enable(struct drm_bridge *bridge,344				struct drm_bridge_state *bridge_state)345{346	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);347	struct drm_atomic_state *state = bridge_state->base.state;348	struct drm_connector_state *conn_state;349	struct drm_connector *connector;350	struct drm_crtc_state *crtc_state;351	unsigned long flags;352	int ret;353 354	/*355	 * None of these should fail, as the bridge can't be enabled without a356	 * valid CRTC to connector path with fully populated new states.357	 */358	connector = drm_atomic_get_new_connector_for_encoder(state,359							     bridge->encoder);360	if (WARN_ON(!connector))361		return;362	conn_state = drm_atomic_get_new_connector_state(state, connector);363	if (WARN_ON(!conn_state))364		return;365	crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);366	if (WARN_ON(!crtc_state))367		return;368 369	hdmi->cfg.hdmi_dvi_mode = connector->display_info.is_hdmi370				? HDMI_HDMI : HDMI_DVI;371 372	if (connector->display_info.is_hdmi) {373		const struct drm_display_mode *mode;374		struct hdmi_avi_infoframe avi;375 376		mode = &crtc_state->adjusted_mode;377		ret = drm_hdmi_avi_infoframe_from_display_mode(&avi, connector,378							       mode);379		if (ret == 0)380			hdmi->cfg.infoframe = avi;381	}382 383	mutex_lock(&hdmi->lock);384 385	ret = hdmi_power_on_full(hdmi);386	if (ret) {387		DSSERR("failed to power on device\n");388		goto done;389	}390 391	if (hdmi->audio_configured) {392		ret = hdmi4_audio_config(&hdmi->core, &hdmi->wp,393					 &hdmi->audio_config,394					 hdmi->cfg.vm.pixelclock);395		if (ret) {396			DSSERR("Error restoring audio configuration: %d", ret);397			hdmi->audio_abort_cb(&hdmi->pdev->dev);398			hdmi->audio_configured = false;399		}400	}401 402	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);403	if (hdmi->audio_configured && hdmi->audio_playing)404		hdmi_start_audio_stream(hdmi);405	hdmi->display_enabled = true;406	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);407 408done:409	mutex_unlock(&hdmi->lock);410}411 412static void hdmi4_bridge_disable(struct drm_bridge *bridge,413				 struct drm_bridge_state *bridge_state)414{415	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);416	unsigned long flags;417 418	mutex_lock(&hdmi->lock);419 420	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);421	hdmi_stop_audio_stream(hdmi);422	hdmi->display_enabled = false;423	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);424 425	hdmi_power_off_full(hdmi);426 427	mutex_unlock(&hdmi->lock);428}429 430static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge,431				    enum drm_connector_status status)432{433	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);434 435	if (status == connector_status_disconnected)436		hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID);437}438 439static const struct drm_edid *hdmi4_bridge_edid_read(struct drm_bridge *bridge,440						     struct drm_connector *connector)441{442	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);443	const struct drm_edid *drm_edid = NULL;444	unsigned int cec_addr;445	bool need_enable;446	int r;447 448	need_enable = hdmi->core_enabled == false;449 450	if (need_enable) {451		r = hdmi4_core_enable(&hdmi->core);452		if (r)453			return NULL;454	}455 456	mutex_lock(&hdmi->lock);457	r = hdmi_runtime_get(hdmi);458	BUG_ON(r);459 460	r = hdmi4_core_ddc_init(&hdmi->core);461	if (r)462		goto done;463 464	drm_edid = drm_edid_read_custom(connector, hdmi4_core_ddc_read, &hdmi->core);465 466done:467	hdmi_runtime_put(hdmi);468	mutex_unlock(&hdmi->lock);469 470	if (drm_edid) {471		/*472		 * FIXME: The CEC physical address should be set using473		 * hdmi4_cec_set_phys_addr(&hdmi->core,474		 * connector->display_info.source_physical_address) from a path475		 * that has read the EDID and called476		 * drm_edid_connector_update().477		 */478		const struct edid *edid = drm_edid_raw(drm_edid);479		unsigned int len = (edid->extensions + 1) * EDID_LENGTH;480 481		cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);482	} else {483		cec_addr = CEC_PHYS_ADDR_INVALID;484	}485 486	hdmi4_cec_set_phys_addr(&hdmi->core, cec_addr);487 488	if (need_enable)489		hdmi4_core_disable(&hdmi->core);490 491	return drm_edid;492}493 494static const struct drm_bridge_funcs hdmi4_bridge_funcs = {495	.attach = hdmi4_bridge_attach,496	.mode_set = hdmi4_bridge_mode_set,497	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,498	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,499	.atomic_reset = drm_atomic_helper_bridge_reset,500	.atomic_enable = hdmi4_bridge_enable,501	.atomic_disable = hdmi4_bridge_disable,502	.hpd_notify = hdmi4_bridge_hpd_notify,503	.edid_read = hdmi4_bridge_edid_read,504};505 506static void hdmi4_bridge_init(struct omap_hdmi *hdmi)507{508	hdmi->bridge.funcs = &hdmi4_bridge_funcs;509	hdmi->bridge.of_node = hdmi->pdev->dev.of_node;510	hdmi->bridge.ops = DRM_BRIDGE_OP_EDID;511	hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;512 513	drm_bridge_add(&hdmi->bridge);514}515 516static void hdmi4_bridge_cleanup(struct omap_hdmi *hdmi)517{518	drm_bridge_remove(&hdmi->bridge);519}520 521/* -----------------------------------------------------------------------------522 * Audio Callbacks523 */524 525static int hdmi_audio_startup(struct device *dev,526			      void (*abort_cb)(struct device *dev))527{528	struct omap_hdmi *hd = dev_get_drvdata(dev);529 530	mutex_lock(&hd->lock);531 532	WARN_ON(hd->audio_abort_cb != NULL);533 534	hd->audio_abort_cb = abort_cb;535 536	mutex_unlock(&hd->lock);537 538	return 0;539}540 541static int hdmi_audio_shutdown(struct device *dev)542{543	struct omap_hdmi *hd = dev_get_drvdata(dev);544 545	mutex_lock(&hd->lock);546	hd->audio_abort_cb = NULL;547	hd->audio_configured = false;548	hd->audio_playing = false;549	mutex_unlock(&hd->lock);550 551	return 0;552}553 554static int hdmi_audio_start(struct device *dev)555{556	struct omap_hdmi *hd = dev_get_drvdata(dev);557	unsigned long flags;558 559	spin_lock_irqsave(&hd->audio_playing_lock, flags);560 561	if (hd->display_enabled) {562		if (!hdmi_mode_has_audio(&hd->cfg))563			DSSERR("%s: Video mode does not support audio\n",564			       __func__);565		hdmi_start_audio_stream(hd);566	}567	hd->audio_playing = true;568 569	spin_unlock_irqrestore(&hd->audio_playing_lock, flags);570	return 0;571}572 573static void hdmi_audio_stop(struct device *dev)574{575	struct omap_hdmi *hd = dev_get_drvdata(dev);576	unsigned long flags;577 578	WARN_ON(!hdmi_mode_has_audio(&hd->cfg));579 580	spin_lock_irqsave(&hd->audio_playing_lock, flags);581 582	if (hd->display_enabled)583		hdmi_stop_audio_stream(hd);584	hd->audio_playing = false;585 586	spin_unlock_irqrestore(&hd->audio_playing_lock, flags);587}588 589static int hdmi_audio_config(struct device *dev,590			     struct omap_dss_audio *dss_audio)591{592	struct omap_hdmi *hd = dev_get_drvdata(dev);593	int ret = 0;594 595	mutex_lock(&hd->lock);596 597	if (hd->display_enabled) {598		ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio,599					 hd->cfg.vm.pixelclock);600		if (ret)601			goto out;602	}603 604	hd->audio_configured = true;605	hd->audio_config = *dss_audio;606out:607	mutex_unlock(&hd->lock);608 609	return ret;610}611 612static const struct omap_hdmi_audio_ops hdmi_audio_ops = {613	.audio_startup = hdmi_audio_startup,614	.audio_shutdown = hdmi_audio_shutdown,615	.audio_start = hdmi_audio_start,616	.audio_stop = hdmi_audio_stop,617	.audio_config = hdmi_audio_config,618};619 620static int hdmi_audio_register(struct omap_hdmi *hdmi)621{622	struct omap_hdmi_audio_pdata pdata = {623		.dev = &hdmi->pdev->dev,624		.version = 4,625		.audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi->wp),626		.ops = &hdmi_audio_ops,627	};628 629	hdmi->audio_pdev = platform_device_register_data(630		&hdmi->pdev->dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO,631		&pdata, sizeof(pdata));632 633	if (IS_ERR(hdmi->audio_pdev))634		return PTR_ERR(hdmi->audio_pdev);635 636	return 0;637}638 639/* -----------------------------------------------------------------------------640 * Component Bind & Unbind641 */642 643static int hdmi4_bind(struct device *dev, struct device *master, void *data)644{645	struct dss_device *dss = dss_get_device(master);646	struct omap_hdmi *hdmi = dev_get_drvdata(dev);647	int r;648 649	hdmi->dss = dss;650 651	r = hdmi_runtime_get(hdmi);652	if (r)653		return r;654 655	r = hdmi_pll_init(dss, hdmi->pdev, &hdmi->pll, &hdmi->wp);656	if (r)657		goto err_runtime_put;658 659	r = hdmi4_cec_init(hdmi->pdev, &hdmi->core, &hdmi->wp);660	if (r)661		goto err_pll_uninit;662 663	r = hdmi_audio_register(hdmi);664	if (r) {665		DSSERR("Registering HDMI audio failed\n");666		goto err_cec_uninit;667	}668 669	hdmi->debugfs = dss_debugfs_create_file(dss, "hdmi", hdmi_dump_regs,670					       hdmi);671 672	hdmi_runtime_put(hdmi);673 674	return 0;675 676err_cec_uninit:677	hdmi4_cec_uninit(&hdmi->core);678err_pll_uninit:679	hdmi_pll_uninit(&hdmi->pll);680err_runtime_put:681	hdmi_runtime_put(hdmi);682	return r;683}684 685static void hdmi4_unbind(struct device *dev, struct device *master, void *data)686{687	struct omap_hdmi *hdmi = dev_get_drvdata(dev);688 689	dss_debugfs_remove_file(hdmi->debugfs);690 691	if (hdmi->audio_pdev)692		platform_device_unregister(hdmi->audio_pdev);693 694	hdmi4_cec_uninit(&hdmi->core);695	hdmi_pll_uninit(&hdmi->pll);696}697 698static const struct component_ops hdmi4_component_ops = {699	.bind	= hdmi4_bind,700	.unbind	= hdmi4_unbind,701};702 703/* -----------------------------------------------------------------------------704 * Probe & Remove, Suspend & Resume705 */706 707static int hdmi4_init_output(struct omap_hdmi *hdmi)708{709	struct omap_dss_device *out = &hdmi->output;710	int r;711 712	hdmi4_bridge_init(hdmi);713 714	out->dev = &hdmi->pdev->dev;715	out->id = OMAP_DSS_OUTPUT_HDMI;716	out->type = OMAP_DISPLAY_TYPE_HDMI;717	out->name = "hdmi.0";718	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;719	out->of_port = 0;720 721	r = omapdss_device_init_output(out, &hdmi->bridge);722	if (r < 0) {723		hdmi4_bridge_cleanup(hdmi);724		return r;725	}726 727	omapdss_device_register(out);728 729	return 0;730}731 732static void hdmi4_uninit_output(struct omap_hdmi *hdmi)733{734	struct omap_dss_device *out = &hdmi->output;735 736	omapdss_device_unregister(out);737	omapdss_device_cleanup_output(out);738 739	hdmi4_bridge_cleanup(hdmi);740}741 742static int hdmi4_probe_of(struct omap_hdmi *hdmi)743{744	struct platform_device *pdev = hdmi->pdev;745	struct device_node *node = pdev->dev.of_node;746	struct device_node *ep;747	int r;748 749	ep = of_graph_get_endpoint_by_regs(node, 0, 0);750	if (!ep)751		return 0;752 753	r = hdmi_parse_lanes_of(pdev, ep, &hdmi->phy);754	of_node_put(ep);755	return r;756}757 758static int hdmi4_probe(struct platform_device *pdev)759{760	struct omap_hdmi *hdmi;761	int irq;762	int r;763 764	hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);765	if (!hdmi)766		return -ENOMEM;767 768	hdmi->pdev = pdev;769 770	dev_set_drvdata(&pdev->dev, hdmi);771 772	mutex_init(&hdmi->lock);773	spin_lock_init(&hdmi->audio_playing_lock);774 775	r = hdmi4_probe_of(hdmi);776	if (r)777		goto err_free;778 779	r = hdmi_wp_init(pdev, &hdmi->wp, 4);780	if (r)781		goto err_free;782 783	r = hdmi_phy_init(pdev, &hdmi->phy, 4);784	if (r)785		goto err_free;786 787	r = hdmi4_core_init(pdev, &hdmi->core);788	if (r)789		goto err_free;790 791	irq = platform_get_irq(pdev, 0);792	if (irq < 0) {793		DSSERR("platform_get_irq failed\n");794		r = -ENODEV;795		goto err_free;796	}797 798	r = devm_request_threaded_irq(&pdev->dev, irq,799			NULL, hdmi_irq_handler,800			IRQF_ONESHOT, "OMAP HDMI", hdmi);801	if (r) {802		DSSERR("HDMI IRQ request failed\n");803		goto err_free;804	}805 806	hdmi->vdda_reg = devm_regulator_get(&pdev->dev, "vdda");807	if (IS_ERR(hdmi->vdda_reg)) {808		r = PTR_ERR(hdmi->vdda_reg);809		if (r != -EPROBE_DEFER)810			DSSERR("can't get VDDA regulator\n");811		goto err_free;812	}813 814	pm_runtime_enable(&pdev->dev);815 816	r = hdmi4_init_output(hdmi);817	if (r)818		goto err_pm_disable;819 820	r = component_add(&pdev->dev, &hdmi4_component_ops);821	if (r)822		goto err_uninit_output;823 824	return 0;825 826err_uninit_output:827	hdmi4_uninit_output(hdmi);828err_pm_disable:829	pm_runtime_disable(&pdev->dev);830err_free:831	kfree(hdmi);832	return r;833}834 835static void hdmi4_remove(struct platform_device *pdev)836{837	struct omap_hdmi *hdmi = platform_get_drvdata(pdev);838 839	component_del(&pdev->dev, &hdmi4_component_ops);840 841	hdmi4_uninit_output(hdmi);842 843	pm_runtime_disable(&pdev->dev);844 845	kfree(hdmi);846}847 848static const struct of_device_id hdmi_of_match[] = {849	{ .compatible = "ti,omap4-hdmi", },850	{},851};852 853struct platform_driver omapdss_hdmi4hw_driver = {854	.probe		= hdmi4_probe,855	.remove_new	= hdmi4_remove,856	.driver         = {857		.name   = "omapdss_hdmi",858		.of_match_table = hdmi_of_match,859		.suppress_bind_attrs = true,860	},861};862