brintos

brintos / linux-shallow public Read only

0
0
Text · 41.4 KiB · 847470f Raw
1501 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) STMicroelectronics SA 20144 * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.5 */6 7#include <linux/clk.h>8#include <linux/component.h>9#include <linux/debugfs.h>10#include <linux/hdmi.h>11#include <linux/i2c.h>12#include <linux/module.h>13#include <linux/io.h>14#include <linux/platform_device.h>15#include <linux/reset.h>16 17#include <drm/drm_atomic_helper.h>18#include <drm/drm_bridge.h>19#include <drm/drm_debugfs.h>20#include <drm/drm_drv.h>21#include <drm/drm_edid.h>22#include <drm/drm_file.h>23#include <drm/drm_print.h>24#include <drm/drm_probe_helper.h>25 26#include <sound/hdmi-codec.h>27 28#include "sti_hdmi.h"29#include "sti_hdmi_tx3g4c28phy.h"30#include "sti_vtg.h"31 32#define HDMI_CFG                        0x000033#define HDMI_INT_EN                     0x000434#define HDMI_INT_STA                    0x000835#define HDMI_INT_CLR                    0x000C36#define HDMI_STA                        0x001037#define HDMI_ACTIVE_VID_XMIN            0x010038#define HDMI_ACTIVE_VID_XMAX            0x010439#define HDMI_ACTIVE_VID_YMIN            0x010840#define HDMI_ACTIVE_VID_YMAX            0x010C41#define HDMI_DFLT_CHL0_DAT              0x011042#define HDMI_DFLT_CHL1_DAT              0x011443#define HDMI_DFLT_CHL2_DAT              0x011844#define HDMI_AUDIO_CFG                  0x020045#define HDMI_SPDIF_FIFO_STATUS          0x020446#define HDMI_SW_DI_1_HEAD_WORD          0x021047#define HDMI_SW_DI_1_PKT_WORD0          0x021448#define HDMI_SW_DI_1_PKT_WORD1          0x021849#define HDMI_SW_DI_1_PKT_WORD2          0x021C50#define HDMI_SW_DI_1_PKT_WORD3          0x022051#define HDMI_SW_DI_1_PKT_WORD4          0x022452#define HDMI_SW_DI_1_PKT_WORD5          0x022853#define HDMI_SW_DI_1_PKT_WORD6          0x022C54#define HDMI_SW_DI_CFG                  0x023055#define HDMI_SAMPLE_FLAT_MASK           0x024456#define HDMI_AUDN                       0x040057#define HDMI_AUD_CTS                    0x040458#define HDMI_SW_DI_2_HEAD_WORD          0x060059#define HDMI_SW_DI_2_PKT_WORD0          0x060460#define HDMI_SW_DI_2_PKT_WORD1          0x060861#define HDMI_SW_DI_2_PKT_WORD2          0x060C62#define HDMI_SW_DI_2_PKT_WORD3          0x061063#define HDMI_SW_DI_2_PKT_WORD4          0x061464#define HDMI_SW_DI_2_PKT_WORD5          0x061865#define HDMI_SW_DI_2_PKT_WORD6          0x061C66#define HDMI_SW_DI_3_HEAD_WORD          0x062067#define HDMI_SW_DI_3_PKT_WORD0          0x062468#define HDMI_SW_DI_3_PKT_WORD1          0x062869#define HDMI_SW_DI_3_PKT_WORD2          0x062C70#define HDMI_SW_DI_3_PKT_WORD3          0x063071#define HDMI_SW_DI_3_PKT_WORD4          0x063472#define HDMI_SW_DI_3_PKT_WORD5          0x063873#define HDMI_SW_DI_3_PKT_WORD6          0x063C74 75#define HDMI_IFRAME_SLOT_AVI            176#define HDMI_IFRAME_SLOT_AUDIO          277#define HDMI_IFRAME_SLOT_VENDOR         378 79#define  XCAT(prefix, x, suffix)        prefix ## x ## suffix80#define  HDMI_SW_DI_N_HEAD_WORD(x)      XCAT(HDMI_SW_DI_, x, _HEAD_WORD)81#define  HDMI_SW_DI_N_PKT_WORD0(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD0)82#define  HDMI_SW_DI_N_PKT_WORD1(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD1)83#define  HDMI_SW_DI_N_PKT_WORD2(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD2)84#define  HDMI_SW_DI_N_PKT_WORD3(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD3)85#define  HDMI_SW_DI_N_PKT_WORD4(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD4)86#define  HDMI_SW_DI_N_PKT_WORD5(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD5)87#define  HDMI_SW_DI_N_PKT_WORD6(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD6)88 89#define HDMI_SW_DI_MAX_WORD             790 91#define HDMI_IFRAME_DISABLED            0x092#define HDMI_IFRAME_SINGLE_SHOT         0x193#define HDMI_IFRAME_FIELD               0x294#define HDMI_IFRAME_FRAME               0x395#define HDMI_IFRAME_MASK                0x396#define HDMI_IFRAME_CFG_DI_N(x, n)       ((x) << ((n-1)*4)) /* n from 1 to 6 */97 98#define HDMI_CFG_DEVICE_EN              BIT(0)99#define HDMI_CFG_HDMI_NOT_DVI           BIT(1)100#define HDMI_CFG_HDCP_EN                BIT(2)101#define HDMI_CFG_ESS_NOT_OESS           BIT(3)102#define HDMI_CFG_H_SYNC_POL_NEG         BIT(4)103#define HDMI_CFG_V_SYNC_POL_NEG         BIT(6)104#define HDMI_CFG_422_EN                 BIT(8)105#define HDMI_CFG_FIFO_OVERRUN_CLR       BIT(12)106#define HDMI_CFG_FIFO_UNDERRUN_CLR      BIT(13)107#define HDMI_CFG_SW_RST_EN              BIT(31)108 109#define HDMI_INT_GLOBAL                 BIT(0)110#define HDMI_INT_SW_RST                 BIT(1)111#define HDMI_INT_PIX_CAP                BIT(3)112#define HDMI_INT_HOT_PLUG               BIT(4)113#define HDMI_INT_DLL_LCK                BIT(5)114#define HDMI_INT_NEW_FRAME              BIT(6)115#define HDMI_INT_GENCTRL_PKT            BIT(7)116#define HDMI_INT_AUDIO_FIFO_XRUN        BIT(8)117#define HDMI_INT_SINK_TERM_PRESENT      BIT(11)118 119#define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \120			| HDMI_INT_DLL_LCK \121			| HDMI_INT_HOT_PLUG \122			| HDMI_INT_GLOBAL)123 124#define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \125			| HDMI_INT_AUDIO_FIFO_XRUN \126			| HDMI_INT_GENCTRL_PKT \127			| HDMI_INT_NEW_FRAME \128			| HDMI_INT_DLL_LCK \129			| HDMI_INT_HOT_PLUG \130			| HDMI_INT_PIX_CAP \131			| HDMI_INT_SW_RST \132			| HDMI_INT_GLOBAL)133 134#define HDMI_STA_SW_RST                 BIT(1)135 136#define HDMI_AUD_CFG_8CH		BIT(0)137#define HDMI_AUD_CFG_SPDIF_DIV_2	BIT(1)138#define HDMI_AUD_CFG_SPDIF_DIV_3	BIT(2)139#define HDMI_AUD_CFG_SPDIF_CLK_DIV_4	(BIT(1) | BIT(2))140#define HDMI_AUD_CFG_CTS_CLK_256FS	BIT(12)141#define HDMI_AUD_CFG_DTS_INVALID	BIT(16)142#define HDMI_AUD_CFG_ONE_BIT_INVALID	(BIT(18) | BIT(19) | BIT(20) |  BIT(21))143#define HDMI_AUD_CFG_CH12_VALID	BIT(28)144#define HDMI_AUD_CFG_CH34_VALID	BIT(29)145#define HDMI_AUD_CFG_CH56_VALID	BIT(30)146#define HDMI_AUD_CFG_CH78_VALID	BIT(31)147 148/* sample flat mask */149#define HDMI_SAMPLE_FLAT_NO	 0150#define HDMI_SAMPLE_FLAT_SP0 BIT(0)151#define HDMI_SAMPLE_FLAT_SP1 BIT(1)152#define HDMI_SAMPLE_FLAT_SP2 BIT(2)153#define HDMI_SAMPLE_FLAT_SP3 BIT(3)154#define HDMI_SAMPLE_FLAT_ALL (HDMI_SAMPLE_FLAT_SP0 | HDMI_SAMPLE_FLAT_SP1 |\155			      HDMI_SAMPLE_FLAT_SP2 | HDMI_SAMPLE_FLAT_SP3)156 157#define HDMI_INFOFRAME_HEADER_TYPE(x)    (((x) & 0xff) <<  0)158#define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)159#define HDMI_INFOFRAME_HEADER_LEN(x)     (((x) & 0x0f) << 16)160 161struct sti_hdmi_connector {162	struct drm_connector drm_connector;163	struct drm_encoder *encoder;164	struct sti_hdmi *hdmi;165	struct drm_property *colorspace_property;166};167 168#define to_sti_hdmi_connector(x) \169	container_of(x, struct sti_hdmi_connector, drm_connector)170 171static const struct drm_prop_enum_list colorspace_mode_names[] = {172	{ HDMI_COLORSPACE_RGB, "rgb" },173	{ HDMI_COLORSPACE_YUV422, "yuv422" },174	{ HDMI_COLORSPACE_YUV444, "yuv444" },175};176 177u32 hdmi_read(struct sti_hdmi *hdmi, int offset)178{179	return readl(hdmi->regs + offset);180}181 182void hdmi_write(struct sti_hdmi *hdmi, u32 val, int offset)183{184	writel(val, hdmi->regs + offset);185}186 187/*188 * HDMI interrupt handler threaded189 *190 * @irq: irq number191 * @arg: connector structure192 */193static irqreturn_t hdmi_irq_thread(int irq, void *arg)194{195	struct sti_hdmi *hdmi = arg;196 197	/* Hot plug/unplug IRQ */198	if (hdmi->irq_status & HDMI_INT_HOT_PLUG) {199		hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG;200		if (hdmi->drm_dev)201			drm_helper_hpd_irq_event(hdmi->drm_dev);202	}203 204	/* Sw reset and PLL lock are exclusive so we can use the same205	 * event to signal them206	 */207	if (hdmi->irq_status & (HDMI_INT_SW_RST | HDMI_INT_DLL_LCK)) {208		hdmi->event_received = true;209		wake_up_interruptible(&hdmi->wait_event);210	}211 212	/* Audio FIFO underrun IRQ */213	if (hdmi->irq_status & HDMI_INT_AUDIO_FIFO_XRUN)214		DRM_INFO("Warning: audio FIFO underrun occurs!\n");215 216	return IRQ_HANDLED;217}218 219/*220 * HDMI interrupt handler221 *222 * @irq: irq number223 * @arg: connector structure224 */225static irqreturn_t hdmi_irq(int irq, void *arg)226{227	struct sti_hdmi *hdmi = arg;228 229	/* read interrupt status */230	hdmi->irq_status = hdmi_read(hdmi, HDMI_INT_STA);231 232	/* clear interrupt status */233	hdmi_write(hdmi, hdmi->irq_status, HDMI_INT_CLR);234 235	/* force sync bus write */236	hdmi_read(hdmi, HDMI_INT_STA);237 238	return IRQ_WAKE_THREAD;239}240 241/*242 * Set hdmi active area depending on the drm display mode selected243 *244 * @hdmi: pointer on the hdmi internal structure245 */246static void hdmi_active_area(struct sti_hdmi *hdmi)247{248	u32 xmin, xmax;249	u32 ymin, ymax;250 251	xmin = sti_vtg_get_pixel_number(hdmi->mode, 1);252	xmax = sti_vtg_get_pixel_number(hdmi->mode, hdmi->mode.hdisplay);253	ymin = sti_vtg_get_line_number(hdmi->mode, 0);254	ymax = sti_vtg_get_line_number(hdmi->mode, hdmi->mode.vdisplay - 1);255 256	hdmi_write(hdmi, xmin, HDMI_ACTIVE_VID_XMIN);257	hdmi_write(hdmi, xmax, HDMI_ACTIVE_VID_XMAX);258	hdmi_write(hdmi, ymin, HDMI_ACTIVE_VID_YMIN);259	hdmi_write(hdmi, ymax, HDMI_ACTIVE_VID_YMAX);260}261 262/*263 * Overall hdmi configuration264 *265 * @hdmi: pointer on the hdmi internal structure266 */267static void hdmi_config(struct sti_hdmi *hdmi)268{269	struct drm_connector *connector = hdmi->drm_connector;270	u32 conf;271 272	DRM_DEBUG_DRIVER("\n");273 274	/* Clear overrun and underrun fifo */275	conf = HDMI_CFG_FIFO_OVERRUN_CLR | HDMI_CFG_FIFO_UNDERRUN_CLR;276 277	/* Select encryption type and the framing mode */278	conf |= HDMI_CFG_ESS_NOT_OESS;279	if (connector->display_info.is_hdmi)280		conf |= HDMI_CFG_HDMI_NOT_DVI;281 282	/* Set Hsync polarity */283	if (hdmi->mode.flags & DRM_MODE_FLAG_NHSYNC) {284		DRM_DEBUG_DRIVER("H Sync Negative\n");285		conf |= HDMI_CFG_H_SYNC_POL_NEG;286	}287 288	/* Set Vsync polarity */289	if (hdmi->mode.flags & DRM_MODE_FLAG_NVSYNC) {290		DRM_DEBUG_DRIVER("V Sync Negative\n");291		conf |= HDMI_CFG_V_SYNC_POL_NEG;292	}293 294	/* Enable HDMI */295	conf |= HDMI_CFG_DEVICE_EN;296 297	hdmi_write(hdmi, conf, HDMI_CFG);298}299 300/*301 * Helper to reset info frame302 *303 * @hdmi: pointer on the hdmi internal structure304 * @slot: infoframe to reset305 */306static void hdmi_infoframe_reset(struct sti_hdmi *hdmi,307				 u32 slot)308{309	u32 val, i;310	u32 head_offset, pack_offset;311 312	switch (slot) {313	case HDMI_IFRAME_SLOT_AVI:314		head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI);315		pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI);316		break;317	case HDMI_IFRAME_SLOT_AUDIO:318		head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO);319		pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO);320		break;321	case HDMI_IFRAME_SLOT_VENDOR:322		head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_VENDOR);323		pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_VENDOR);324		break;325	default:326		DRM_ERROR("unsupported infoframe slot: %#x\n", slot);327		return;328	}329 330	/* Disable transmission for the selected slot */331	val = hdmi_read(hdmi, HDMI_SW_DI_CFG);332	val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, slot);333	hdmi_write(hdmi, val, HDMI_SW_DI_CFG);334 335	/* Reset info frame registers */336	hdmi_write(hdmi, 0x0, head_offset);337	for (i = 0; i < HDMI_SW_DI_MAX_WORD; i += sizeof(u32))338		hdmi_write(hdmi, 0x0, pack_offset + i);339}340 341/*342 * Helper to concatenate infoframe in 32 bits word343 *344 * @ptr: pointer on the hdmi internal structure345 * @size: size to write346 */347static inline unsigned int hdmi_infoframe_subpack(const u8 *ptr, size_t size)348{349	unsigned long value = 0;350	size_t i;351 352	for (i = size; i > 0; i--)353		value = (value << 8) | ptr[i - 1];354 355	return value;356}357 358/*359 * Helper to write info frame360 *361 * @hdmi: pointer on the hdmi internal structure362 * @data: infoframe to write363 * @size: size to write364 */365static void hdmi_infoframe_write_infopack(struct sti_hdmi *hdmi,366					  const u8 *data,367					  size_t size)368{369	const u8 *ptr = data;370	u32 val, slot, mode, i;371	u32 head_offset, pack_offset;372 373	switch (*ptr) {374	case HDMI_INFOFRAME_TYPE_AVI:375		slot = HDMI_IFRAME_SLOT_AVI;376		mode = HDMI_IFRAME_FIELD;377		head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI);378		pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI);379		break;380	case HDMI_INFOFRAME_TYPE_AUDIO:381		slot = HDMI_IFRAME_SLOT_AUDIO;382		mode = HDMI_IFRAME_FRAME;383		head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO);384		pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO);385		break;386	case HDMI_INFOFRAME_TYPE_VENDOR:387		slot = HDMI_IFRAME_SLOT_VENDOR;388		mode = HDMI_IFRAME_FRAME;389		head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_VENDOR);390		pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_VENDOR);391		break;392	default:393		DRM_ERROR("unsupported infoframe type: %#x\n", *ptr);394		return;395	}396 397	/* Disable transmission slot for updated infoframe */398	val = hdmi_read(hdmi, HDMI_SW_DI_CFG);399	val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, slot);400	hdmi_write(hdmi, val, HDMI_SW_DI_CFG);401 402	val = HDMI_INFOFRAME_HEADER_TYPE(*ptr++);403	val |= HDMI_INFOFRAME_HEADER_VERSION(*ptr++);404	val |= HDMI_INFOFRAME_HEADER_LEN(*ptr++);405	writel(val, hdmi->regs + head_offset);406 407	/*408	 * Each subpack contains 4 bytes409	 * The First Bytes of the first subpacket must contain the checksum410	 * Packet size is increase by one.411	 */412	size = size - HDMI_INFOFRAME_HEADER_SIZE + 1;413	for (i = 0; i < size; i += sizeof(u32)) {414		size_t num;415 416		num = min_t(size_t, size - i, sizeof(u32));417		val = hdmi_infoframe_subpack(ptr, num);418		ptr += sizeof(u32);419		writel(val, hdmi->regs + pack_offset + i);420	}421 422	/* Enable transmission slot for updated infoframe */423	val = hdmi_read(hdmi, HDMI_SW_DI_CFG);424	val |= HDMI_IFRAME_CFG_DI_N(mode, slot);425	hdmi_write(hdmi, val, HDMI_SW_DI_CFG);426}427 428/*429 * Prepare and configure the AVI infoframe430 *431 * AVI infoframe are transmitted at least once per two video field and432 * contains information about HDMI transmission mode such as color space,433 * colorimetry, ...434 *435 * @hdmi: pointer on the hdmi internal structure436 *437 * Return negative value if error occurs438 */439static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)440{441	struct drm_display_mode *mode = &hdmi->mode;442	struct hdmi_avi_infoframe infoframe;443	u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];444	int ret;445 446	DRM_DEBUG_DRIVER("\n");447 448	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe,449						       hdmi->drm_connector, mode);450	if (ret < 0) {451		DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);452		return ret;453	}454 455	/* fixed infoframe configuration not linked to the mode */456	infoframe.colorspace = hdmi->colorspace;457	infoframe.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;458	infoframe.colorimetry = HDMI_COLORIMETRY_NONE;459 460	ret = hdmi_avi_infoframe_pack(&infoframe, buffer, sizeof(buffer));461	if (ret < 0) {462		DRM_ERROR("failed to pack AVI infoframe: %d\n", ret);463		return ret;464	}465 466	hdmi_infoframe_write_infopack(hdmi, buffer, ret);467 468	return 0;469}470 471/*472 * Prepare and configure the AUDIO infoframe473 *474 * AUDIO infoframe are transmitted once per frame and475 * contains information about HDMI transmission mode such as audio codec,476 * sample size, ...477 *478 * @hdmi: pointer on the hdmi internal structure479 *480 * Return negative value if error occurs481 */482static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)483{484	struct hdmi_audio_params *audio = &hdmi->audio;485	u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];486	int ret, val;487 488	DRM_DEBUG_DRIVER("enter %s, AIF %s\n", __func__,489			 audio->enabled ? "enable" : "disable");490	if (audio->enabled) {491		/* set audio parameters stored*/492		ret = hdmi_audio_infoframe_pack(&audio->cea, buffer,493						sizeof(buffer));494		if (ret < 0) {495			DRM_ERROR("failed to pack audio infoframe: %d\n", ret);496			return ret;497		}498		hdmi_infoframe_write_infopack(hdmi, buffer, ret);499	} else {500		/*disable audio info frame transmission */501		val = hdmi_read(hdmi, HDMI_SW_DI_CFG);502		val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK,503					     HDMI_IFRAME_SLOT_AUDIO);504		hdmi_write(hdmi, val, HDMI_SW_DI_CFG);505	}506 507	return 0;508}509 510/*511 * Prepare and configure the VS infoframe512 *513 * Vendor Specific infoframe are transmitted once per frame and514 * contains vendor specific information.515 *516 * @hdmi: pointer on the hdmi internal structure517 *518 * Return negative value if error occurs519 */520#define HDMI_VENDOR_INFOFRAME_MAX_SIZE 6521static int hdmi_vendor_infoframe_config(struct sti_hdmi *hdmi)522{523	struct drm_display_mode *mode = &hdmi->mode;524	struct hdmi_vendor_infoframe infoframe;525	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_VENDOR_INFOFRAME_MAX_SIZE];526	int ret;527 528	DRM_DEBUG_DRIVER("\n");529 530	ret = drm_hdmi_vendor_infoframe_from_display_mode(&infoframe,531							  hdmi->drm_connector,532							  mode);533	if (ret < 0) {534		/*535		 * Going into that statement does not means vendor infoframe536		 * fails. It just informed us that vendor infoframe is not537		 * needed for the selected mode. Only  4k or stereoscopic 3D538		 * mode requires vendor infoframe. So just simply return 0.539		 */540		return 0;541	}542 543	ret = hdmi_vendor_infoframe_pack(&infoframe, buffer, sizeof(buffer));544	if (ret < 0) {545		DRM_ERROR("failed to pack VS infoframe: %d\n", ret);546		return ret;547	}548 549	hdmi_infoframe_write_infopack(hdmi, buffer, ret);550 551	return 0;552}553 554#define HDMI_TIMEOUT_SWRESET  100   /*milliseconds */555 556/*557 * Software reset of the hdmi subsystem558 *559 * @hdmi: pointer on the hdmi internal structure560 *561 */562static void hdmi_swreset(struct sti_hdmi *hdmi)563{564	u32 val;565 566	DRM_DEBUG_DRIVER("\n");567 568	/* Enable hdmi_audio clock only during hdmi reset */569	if (clk_prepare_enable(hdmi->clk_audio))570		DRM_INFO("Failed to prepare/enable hdmi_audio clk\n");571 572	/* Sw reset */573	hdmi->event_received = false;574 575	val = hdmi_read(hdmi, HDMI_CFG);576	val |= HDMI_CFG_SW_RST_EN;577	hdmi_write(hdmi, val, HDMI_CFG);578 579	/* Wait reset completed */580	wait_event_interruptible_timeout(hdmi->wait_event,581					 hdmi->event_received,582					 msecs_to_jiffies583					 (HDMI_TIMEOUT_SWRESET));584 585	/*586	 * HDMI_STA_SW_RST bit is set to '1' when SW_RST bit in HDMI_CFG is587	 * set to '1' and clk_audio is running.588	 */589	if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_SW_RST) == 0)590		DRM_DEBUG_DRIVER("Warning: HDMI sw reset timeout occurs\n");591 592	val = hdmi_read(hdmi, HDMI_CFG);593	val &= ~HDMI_CFG_SW_RST_EN;594	hdmi_write(hdmi, val, HDMI_CFG);595 596	/* Disable hdmi_audio clock. Not used anymore for drm purpose */597	clk_disable_unprepare(hdmi->clk_audio);598}599 600#define DBGFS_PRINT_STR(str1, str2) seq_printf(s, "%-24s %s\n", str1, str2)601#define DBGFS_PRINT_INT(str1, int2) seq_printf(s, "%-24s %d\n", str1, int2)602#define DBGFS_DUMP(str, reg) seq_printf(s, "%s  %-25s 0x%08X", str, #reg, \603					hdmi_read(hdmi, reg))604#define DBGFS_DUMP_DI(reg, slot) DBGFS_DUMP("\n", reg(slot))605 606static void hdmi_dbg_cfg(struct seq_file *s, int val)607{608	int tmp;609 610	seq_putc(s, '\t');611	tmp = val & HDMI_CFG_HDMI_NOT_DVI;612	DBGFS_PRINT_STR("mode:", tmp ? "HDMI" : "DVI");613	seq_puts(s, "\t\t\t\t\t");614	tmp = val & HDMI_CFG_HDCP_EN;615	DBGFS_PRINT_STR("HDCP:", tmp ? "enable" : "disable");616	seq_puts(s, "\t\t\t\t\t");617	tmp = val & HDMI_CFG_ESS_NOT_OESS;618	DBGFS_PRINT_STR("HDCP mode:", tmp ? "ESS enable" : "OESS enable");619	seq_puts(s, "\t\t\t\t\t");620	tmp = val & HDMI_CFG_H_SYNC_POL_NEG;621	DBGFS_PRINT_STR("Hsync polarity:", tmp ? "inverted" : "normal");622	seq_puts(s, "\t\t\t\t\t");623	tmp = val & HDMI_CFG_V_SYNC_POL_NEG;624	DBGFS_PRINT_STR("Vsync polarity:", tmp ? "inverted" : "normal");625	seq_puts(s, "\t\t\t\t\t");626	tmp = val & HDMI_CFG_422_EN;627	DBGFS_PRINT_STR("YUV422 format:", tmp ? "enable" : "disable");628}629 630static void hdmi_dbg_sta(struct seq_file *s, int val)631{632	int tmp;633 634	seq_putc(s, '\t');635	tmp = (val & HDMI_STA_DLL_LCK);636	DBGFS_PRINT_STR("pll:", tmp ? "locked" : "not locked");637	seq_puts(s, "\t\t\t\t\t");638	tmp = (val & HDMI_STA_HOT_PLUG);639	DBGFS_PRINT_STR("hdmi cable:", tmp ? "connected" : "not connected");640}641 642static void hdmi_dbg_sw_di_cfg(struct seq_file *s, int val)643{644	int tmp;645	char *const en_di[] = {"no transmission",646			       "single transmission",647			       "once every field",648			       "once every frame"};649 650	seq_putc(s, '\t');651	tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 1));652	DBGFS_PRINT_STR("Data island 1:", en_di[tmp]);653	seq_puts(s, "\t\t\t\t\t");654	tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 2)) >> 4;655	DBGFS_PRINT_STR("Data island 2:", en_di[tmp]);656	seq_puts(s, "\t\t\t\t\t");657	tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 3)) >> 8;658	DBGFS_PRINT_STR("Data island 3:", en_di[tmp]);659	seq_puts(s, "\t\t\t\t\t");660	tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 4)) >> 12;661	DBGFS_PRINT_STR("Data island 4:", en_di[tmp]);662	seq_puts(s, "\t\t\t\t\t");663	tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 5)) >> 16;664	DBGFS_PRINT_STR("Data island 5:", en_di[tmp]);665	seq_puts(s, "\t\t\t\t\t");666	tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 6)) >> 20;667	DBGFS_PRINT_STR("Data island 6:", en_di[tmp]);668}669 670static int hdmi_dbg_show(struct seq_file *s, void *data)671{672	struct drm_info_node *node = s->private;673	struct sti_hdmi *hdmi = (struct sti_hdmi *)node->info_ent->data;674 675	seq_printf(s, "HDMI: (vaddr = 0x%p)", hdmi->regs);676	DBGFS_DUMP("\n", HDMI_CFG);677	hdmi_dbg_cfg(s, hdmi_read(hdmi, HDMI_CFG));678	DBGFS_DUMP("", HDMI_INT_EN);679	DBGFS_DUMP("\n", HDMI_STA);680	hdmi_dbg_sta(s, hdmi_read(hdmi, HDMI_STA));681	DBGFS_DUMP("", HDMI_ACTIVE_VID_XMIN);682	seq_putc(s, '\t');683	DBGFS_PRINT_INT("Xmin:", hdmi_read(hdmi, HDMI_ACTIVE_VID_XMIN));684	DBGFS_DUMP("", HDMI_ACTIVE_VID_XMAX);685	seq_putc(s, '\t');686	DBGFS_PRINT_INT("Xmax:", hdmi_read(hdmi, HDMI_ACTIVE_VID_XMAX));687	DBGFS_DUMP("", HDMI_ACTIVE_VID_YMIN);688	seq_putc(s, '\t');689	DBGFS_PRINT_INT("Ymin:", hdmi_read(hdmi, HDMI_ACTIVE_VID_YMIN));690	DBGFS_DUMP("", HDMI_ACTIVE_VID_YMAX);691	seq_putc(s, '\t');692	DBGFS_PRINT_INT("Ymax:", hdmi_read(hdmi, HDMI_ACTIVE_VID_YMAX));693	DBGFS_DUMP("", HDMI_SW_DI_CFG);694	hdmi_dbg_sw_di_cfg(s, hdmi_read(hdmi, HDMI_SW_DI_CFG));695 696	DBGFS_DUMP("\n", HDMI_AUDIO_CFG);697	DBGFS_DUMP("\n", HDMI_SPDIF_FIFO_STATUS);698	DBGFS_DUMP("\n", HDMI_AUDN);699 700	seq_printf(s, "\n AVI Infoframe (Data Island slot N=%d):",701		   HDMI_IFRAME_SLOT_AVI);702	DBGFS_DUMP_DI(HDMI_SW_DI_N_HEAD_WORD, HDMI_IFRAME_SLOT_AVI);703	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD0, HDMI_IFRAME_SLOT_AVI);704	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD1, HDMI_IFRAME_SLOT_AVI);705	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD2, HDMI_IFRAME_SLOT_AVI);706	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD3, HDMI_IFRAME_SLOT_AVI);707	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD4, HDMI_IFRAME_SLOT_AVI);708	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD5, HDMI_IFRAME_SLOT_AVI);709	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD6, HDMI_IFRAME_SLOT_AVI);710	seq_printf(s, "\n\n AUDIO Infoframe (Data Island slot N=%d):",711		   HDMI_IFRAME_SLOT_AUDIO);712	DBGFS_DUMP_DI(HDMI_SW_DI_N_HEAD_WORD, HDMI_IFRAME_SLOT_AUDIO);713	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD0, HDMI_IFRAME_SLOT_AUDIO);714	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD1, HDMI_IFRAME_SLOT_AUDIO);715	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD2, HDMI_IFRAME_SLOT_AUDIO);716	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD3, HDMI_IFRAME_SLOT_AUDIO);717	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD4, HDMI_IFRAME_SLOT_AUDIO);718	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD5, HDMI_IFRAME_SLOT_AUDIO);719	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD6, HDMI_IFRAME_SLOT_AUDIO);720	seq_printf(s, "\n\n VENDOR SPECIFIC Infoframe (Data Island slot N=%d):",721		   HDMI_IFRAME_SLOT_VENDOR);722	DBGFS_DUMP_DI(HDMI_SW_DI_N_HEAD_WORD, HDMI_IFRAME_SLOT_VENDOR);723	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD0, HDMI_IFRAME_SLOT_VENDOR);724	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD1, HDMI_IFRAME_SLOT_VENDOR);725	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD2, HDMI_IFRAME_SLOT_VENDOR);726	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD3, HDMI_IFRAME_SLOT_VENDOR);727	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD4, HDMI_IFRAME_SLOT_VENDOR);728	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD5, HDMI_IFRAME_SLOT_VENDOR);729	DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD6, HDMI_IFRAME_SLOT_VENDOR);730	seq_putc(s, '\n');731	return 0;732}733 734static struct drm_info_list hdmi_debugfs_files[] = {735	{ "hdmi", hdmi_dbg_show, 0, NULL },736};737 738static void hdmi_debugfs_init(struct sti_hdmi *hdmi, struct drm_minor *minor)739{740	unsigned int i;741 742	for (i = 0; i < ARRAY_SIZE(hdmi_debugfs_files); i++)743		hdmi_debugfs_files[i].data = hdmi;744 745	drm_debugfs_create_files(hdmi_debugfs_files,746				 ARRAY_SIZE(hdmi_debugfs_files),747				 minor->debugfs_root, minor);748}749 750static void sti_hdmi_disable(struct drm_bridge *bridge)751{752	struct sti_hdmi *hdmi = bridge->driver_private;753 754	u32 val = hdmi_read(hdmi, HDMI_CFG);755 756	if (!hdmi->enabled)757		return;758 759	DRM_DEBUG_DRIVER("\n");760 761	/* Disable HDMI */762	val &= ~HDMI_CFG_DEVICE_EN;763	hdmi_write(hdmi, val, HDMI_CFG);764 765	hdmi_write(hdmi, 0xffffffff, HDMI_INT_CLR);766 767	/* Stop the phy */768	hdmi->phy_ops->stop(hdmi);769 770	/* Reset info frame transmission */771	hdmi_infoframe_reset(hdmi, HDMI_IFRAME_SLOT_AVI);772	hdmi_infoframe_reset(hdmi, HDMI_IFRAME_SLOT_AUDIO);773	hdmi_infoframe_reset(hdmi, HDMI_IFRAME_SLOT_VENDOR);774 775	/* Set the default channel data to be a dark red */776	hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL0_DAT);777	hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL1_DAT);778	hdmi_write(hdmi, 0x0060, HDMI_DFLT_CHL2_DAT);779 780	/* Disable/unprepare hdmi clock */781	clk_disable_unprepare(hdmi->clk_phy);782	clk_disable_unprepare(hdmi->clk_tmds);783	clk_disable_unprepare(hdmi->clk_pix);784 785	hdmi->enabled = false;786 787	cec_notifier_set_phys_addr(hdmi->notifier, CEC_PHYS_ADDR_INVALID);788}789 790/*791 * sti_hdmi_audio_get_non_coherent_n() - get N parameter for non-coherent792 * clocks. None-coherent clocks means that audio and TMDS clocks have not the793 * same source (drifts between clocks). In this case assumption is that CTS is794 * automatically calculated by hardware.795 *796 * @audio_fs: audio frame clock frequency in Hz797 *798 * Values computed are based on table described in HDMI specification 1.4b799 *800 * Returns n value.801 */802static int sti_hdmi_audio_get_non_coherent_n(unsigned int audio_fs)803{804	unsigned int n;805 806	switch (audio_fs) {807	case 32000:808		n = 4096;809		break;810	case 44100:811		n = 6272;812		break;813	case 48000:814		n = 6144;815		break;816	case 88200:817		n = 6272 * 2;818		break;819	case 96000:820		n = 6144 * 2;821		break;822	case 176400:823		n = 6272 * 4;824		break;825	case 192000:826		n = 6144 * 4;827		break;828	default:829		/* Not pre-defined, recommended value: 128 * fs / 1000 */830		n = (audio_fs * 128) / 1000;831	}832 833	return n;834}835 836static int hdmi_audio_configure(struct sti_hdmi *hdmi)837{838	int audio_cfg, n;839	struct hdmi_audio_params *params = &hdmi->audio;840	struct hdmi_audio_infoframe *info = &params->cea;841 842	DRM_DEBUG_DRIVER("\n");843 844	if (!hdmi->enabled)845		return 0;846 847	/* update N parameter */848	n = sti_hdmi_audio_get_non_coherent_n(params->sample_rate);849 850	DRM_DEBUG_DRIVER("Audio rate = %d Hz, TMDS clock = %d Hz, n = %d\n",851			 params->sample_rate, hdmi->mode.clock * 1000, n);852	hdmi_write(hdmi, n, HDMI_AUDN);853 854	/* update HDMI registers according to configuration */855	audio_cfg = HDMI_AUD_CFG_SPDIF_DIV_2 | HDMI_AUD_CFG_DTS_INVALID |856		    HDMI_AUD_CFG_ONE_BIT_INVALID;857 858	switch (info->channels) {859	case 8:860		audio_cfg |= HDMI_AUD_CFG_CH78_VALID;861		fallthrough;862	case 6:863		audio_cfg |= HDMI_AUD_CFG_CH56_VALID;864		fallthrough;865	case 4:866		audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH;867		fallthrough;868	case 2:869		audio_cfg |= HDMI_AUD_CFG_CH12_VALID;870		break;871	default:872		DRM_ERROR("ERROR: Unsupported number of channels (%d)!\n",873			  info->channels);874		return -EINVAL;875	}876 877	hdmi_write(hdmi, audio_cfg, HDMI_AUDIO_CFG);878 879	return hdmi_audio_infoframe_config(hdmi);880}881 882static void sti_hdmi_pre_enable(struct drm_bridge *bridge)883{884	struct sti_hdmi *hdmi = bridge->driver_private;885 886	DRM_DEBUG_DRIVER("\n");887 888	if (hdmi->enabled)889		return;890 891	/* Prepare/enable clocks */892	if (clk_prepare_enable(hdmi->clk_pix))893		DRM_ERROR("Failed to prepare/enable hdmi_pix clk\n");894	if (clk_prepare_enable(hdmi->clk_tmds))895		DRM_ERROR("Failed to prepare/enable hdmi_tmds clk\n");896	if (clk_prepare_enable(hdmi->clk_phy))897		DRM_ERROR("Failed to prepare/enable hdmi_rejection_pll clk\n");898 899	hdmi->enabled = true;900 901	/* Program hdmi serializer and start phy */902	if (!hdmi->phy_ops->start(hdmi)) {903		DRM_ERROR("Unable to start hdmi phy\n");904		return;905	}906 907	/* Program hdmi active area */908	hdmi_active_area(hdmi);909 910	/* Enable working interrupts */911	hdmi_write(hdmi, HDMI_WORKING_INT, HDMI_INT_EN);912 913	/* Program hdmi config */914	hdmi_config(hdmi);915 916	/* Program AVI infoframe */917	if (hdmi_avi_infoframe_config(hdmi))918		DRM_ERROR("Unable to configure AVI infoframe\n");919 920	if (hdmi->audio.enabled) {921		if (hdmi_audio_configure(hdmi))922			DRM_ERROR("Unable to configure audio\n");923	} else {924		hdmi_audio_infoframe_config(hdmi);925	}926 927	/* Program VS infoframe */928	if (hdmi_vendor_infoframe_config(hdmi))929		DRM_ERROR("Unable to configure VS infoframe\n");930 931	/* Sw reset */932	hdmi_swreset(hdmi);933}934 935static void sti_hdmi_set_mode(struct drm_bridge *bridge,936			      const struct drm_display_mode *mode,937			      const struct drm_display_mode *adjusted_mode)938{939	struct sti_hdmi *hdmi = bridge->driver_private;940	int ret;941 942	DRM_DEBUG_DRIVER("\n");943 944	/* Copy the drm display mode in the connector local structure */945	drm_mode_copy(&hdmi->mode, mode);946 947	/* Update clock framerate according to the selected mode */948	ret = clk_set_rate(hdmi->clk_pix, mode->clock * 1000);949	if (ret < 0) {950		DRM_ERROR("Cannot set rate (%dHz) for hdmi_pix clk\n",951			  mode->clock * 1000);952		return;953	}954	ret = clk_set_rate(hdmi->clk_phy, mode->clock * 1000);955	if (ret < 0) {956		DRM_ERROR("Cannot set rate (%dHz) for hdmi_rejection_pll clk\n",957			  mode->clock * 1000);958		return;959	}960}961 962static void sti_hdmi_bridge_nope(struct drm_bridge *bridge)963{964	/* do nothing */965}966 967static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = {968	.pre_enable = sti_hdmi_pre_enable,969	.enable = sti_hdmi_bridge_nope,970	.disable = sti_hdmi_disable,971	.post_disable = sti_hdmi_bridge_nope,972	.mode_set = sti_hdmi_set_mode,973};974 975static int sti_hdmi_connector_get_modes(struct drm_connector *connector)976{977	const struct drm_display_info *info = &connector->display_info;978	struct sti_hdmi_connector *hdmi_connector979		= to_sti_hdmi_connector(connector);980	struct sti_hdmi *hdmi = hdmi_connector->hdmi;981	const struct drm_edid *drm_edid;982	int count;983 984	DRM_DEBUG_DRIVER("\n");985 986	drm_edid = drm_edid_read(connector);987 988	drm_edid_connector_update(connector, drm_edid);989 990	cec_notifier_set_phys_addr(hdmi->notifier,991				   connector->display_info.source_physical_address);992 993	if (!drm_edid)994		goto fail;995 996	count = drm_edid_connector_add_modes(connector);997 998	DRM_DEBUG_KMS("%s : %dx%d cm\n",999		      info->is_hdmi ? "hdmi monitor" : "dvi monitor",1000		      info->width_mm / 10, info->height_mm / 10);1001 1002	drm_edid_free(drm_edid);1003	return count;1004 1005fail:1006	DRM_ERROR("Can't read HDMI EDID\n");1007	return 0;1008}1009 1010#define CLK_TOLERANCE_HZ 501011 1012static enum drm_mode_status1013sti_hdmi_connector_mode_valid(struct drm_connector *connector,1014			      struct drm_display_mode *mode)1015{1016	int target = mode->clock * 1000;1017	int target_min = target - CLK_TOLERANCE_HZ;1018	int target_max = target + CLK_TOLERANCE_HZ;1019	int result;1020	struct sti_hdmi_connector *hdmi_connector1021		= to_sti_hdmi_connector(connector);1022	struct sti_hdmi *hdmi = hdmi_connector->hdmi;1023 1024 1025	result = clk_round_rate(hdmi->clk_pix, target);1026 1027	DRM_DEBUG_DRIVER("target rate = %d => available rate = %d\n",1028			 target, result);1029 1030	if ((result < target_min) || (result > target_max)) {1031		DRM_DEBUG_DRIVER("hdmi pixclk=%d not supported\n", target);1032		return MODE_BAD;1033	}1034 1035	return MODE_OK;1036}1037 1038static const1039struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {1040	.get_modes = sti_hdmi_connector_get_modes,1041	.mode_valid = sti_hdmi_connector_mode_valid,1042};1043 1044/* get detection status of display device */1045static enum drm_connector_status1046sti_hdmi_connector_detect(struct drm_connector *connector, bool force)1047{1048	struct sti_hdmi_connector *hdmi_connector1049		= to_sti_hdmi_connector(connector);1050	struct sti_hdmi *hdmi = hdmi_connector->hdmi;1051 1052	DRM_DEBUG_DRIVER("\n");1053 1054	if (hdmi->hpd) {1055		DRM_DEBUG_DRIVER("hdmi cable connected\n");1056		return connector_status_connected;1057	}1058 1059	DRM_DEBUG_DRIVER("hdmi cable disconnected\n");1060	cec_notifier_set_phys_addr(hdmi->notifier, CEC_PHYS_ADDR_INVALID);1061	return connector_status_disconnected;1062}1063 1064static void sti_hdmi_connector_init_property(struct drm_device *drm_dev,1065					     struct drm_connector *connector)1066{1067	struct sti_hdmi_connector *hdmi_connector1068		= to_sti_hdmi_connector(connector);1069	struct sti_hdmi *hdmi = hdmi_connector->hdmi;1070	struct drm_property *prop;1071 1072	/* colorspace property */1073	hdmi->colorspace = DEFAULT_COLORSPACE_MODE;1074	prop = drm_property_create_enum(drm_dev, 0, "colorspace",1075					colorspace_mode_names,1076					ARRAY_SIZE(colorspace_mode_names));1077	if (!prop) {1078		DRM_ERROR("fails to create colorspace property\n");1079		return;1080	}1081	hdmi_connector->colorspace_property = prop;1082	drm_object_attach_property(&connector->base, prop, hdmi->colorspace);1083}1084 1085static int1086sti_hdmi_connector_set_property(struct drm_connector *connector,1087				struct drm_connector_state *state,1088				struct drm_property *property,1089				uint64_t val)1090{1091	struct sti_hdmi_connector *hdmi_connector1092		= to_sti_hdmi_connector(connector);1093	struct sti_hdmi *hdmi = hdmi_connector->hdmi;1094 1095	if (property == hdmi_connector->colorspace_property) {1096		hdmi->colorspace = val;1097		return 0;1098	}1099 1100	DRM_ERROR("failed to set hdmi connector property\n");1101	return -EINVAL;1102}1103 1104static int1105sti_hdmi_connector_get_property(struct drm_connector *connector,1106				const struct drm_connector_state *state,1107				struct drm_property *property,1108				uint64_t *val)1109{1110	struct sti_hdmi_connector *hdmi_connector1111		= to_sti_hdmi_connector(connector);1112	struct sti_hdmi *hdmi = hdmi_connector->hdmi;1113 1114	if (property == hdmi_connector->colorspace_property) {1115		*val = hdmi->colorspace;1116		return 0;1117	}1118 1119	DRM_ERROR("failed to get hdmi connector property\n");1120	return -EINVAL;1121}1122 1123static int sti_hdmi_late_register(struct drm_connector *connector)1124{1125	struct sti_hdmi_connector *hdmi_connector1126		= to_sti_hdmi_connector(connector);1127	struct sti_hdmi *hdmi = hdmi_connector->hdmi;1128 1129	hdmi_debugfs_init(hdmi, hdmi->drm_dev->primary);1130 1131	return 0;1132}1133 1134static const struct drm_connector_funcs sti_hdmi_connector_funcs = {1135	.fill_modes = drm_helper_probe_single_connector_modes,1136	.detect = sti_hdmi_connector_detect,1137	.destroy = drm_connector_cleanup,1138	.reset = drm_atomic_helper_connector_reset,1139	.atomic_set_property = sti_hdmi_connector_set_property,1140	.atomic_get_property = sti_hdmi_connector_get_property,1141	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,1142	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,1143	.late_register = sti_hdmi_late_register,1144};1145 1146static struct drm_encoder *sti_hdmi_find_encoder(struct drm_device *dev)1147{1148	struct drm_encoder *encoder;1149 1150	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {1151		if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)1152			return encoder;1153	}1154 1155	return NULL;1156}1157 1158static void hdmi_audio_shutdown(struct device *dev, void *data)1159{1160	struct sti_hdmi *hdmi = dev_get_drvdata(dev);1161	int audio_cfg;1162 1163	DRM_DEBUG_DRIVER("\n");1164 1165	/* disable audio */1166	audio_cfg = HDMI_AUD_CFG_SPDIF_DIV_2 | HDMI_AUD_CFG_DTS_INVALID |1167		    HDMI_AUD_CFG_ONE_BIT_INVALID;1168	hdmi_write(hdmi, audio_cfg, HDMI_AUDIO_CFG);1169 1170	hdmi->audio.enabled = false;1171	hdmi_audio_infoframe_config(hdmi);1172}1173 1174static int hdmi_audio_hw_params(struct device *dev,1175				void *data,1176				struct hdmi_codec_daifmt *daifmt,1177				struct hdmi_codec_params *params)1178{1179	struct sti_hdmi *hdmi = dev_get_drvdata(dev);1180	int ret;1181 1182	DRM_DEBUG_DRIVER("\n");1183 1184	if ((daifmt->fmt != HDMI_I2S) || daifmt->bit_clk_inv ||1185	    daifmt->frame_clk_inv || daifmt->bit_clk_provider ||1186	    daifmt->frame_clk_provider) {1187		dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,1188			daifmt->bit_clk_inv, daifmt->frame_clk_inv,1189			daifmt->bit_clk_provider,1190			daifmt->frame_clk_provider);1191		return -EINVAL;1192	}1193 1194	hdmi->audio.sample_width = params->sample_width;1195	hdmi->audio.sample_rate = params->sample_rate;1196	hdmi->audio.cea = params->cea;1197 1198	hdmi->audio.enabled = true;1199 1200	ret = hdmi_audio_configure(hdmi);1201	if (ret < 0)1202		return ret;1203 1204	return 0;1205}1206 1207static int hdmi_audio_mute(struct device *dev, void *data,1208			   bool enable, int direction)1209{1210	struct sti_hdmi *hdmi = dev_get_drvdata(dev);1211 1212	DRM_DEBUG_DRIVER("%s\n", enable ? "enable" : "disable");1213 1214	if (enable)1215		hdmi_write(hdmi, HDMI_SAMPLE_FLAT_ALL, HDMI_SAMPLE_FLAT_MASK);1216	else1217		hdmi_write(hdmi, HDMI_SAMPLE_FLAT_NO, HDMI_SAMPLE_FLAT_MASK);1218 1219	return 0;1220}1221 1222static int hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf, size_t len)1223{1224	struct sti_hdmi *hdmi = dev_get_drvdata(dev);1225	struct drm_connector *connector = hdmi->drm_connector;1226 1227	DRM_DEBUG_DRIVER("\n");1228	memcpy(buf, connector->eld, min(sizeof(connector->eld), len));1229 1230	return 0;1231}1232 1233static const struct hdmi_codec_ops audio_codec_ops = {1234	.hw_params = hdmi_audio_hw_params,1235	.audio_shutdown = hdmi_audio_shutdown,1236	.mute_stream = hdmi_audio_mute,1237	.get_eld = hdmi_audio_get_eld,1238	.no_capture_mute = 1,1239};1240 1241static int sti_hdmi_register_audio_driver(struct device *dev,1242					  struct sti_hdmi *hdmi)1243{1244	struct hdmi_codec_pdata codec_data = {1245		.ops = &audio_codec_ops,1246		.max_i2s_channels = 8,1247		.i2s = 1,1248	};1249 1250	DRM_DEBUG_DRIVER("\n");1251 1252	hdmi->audio.enabled = false;1253 1254	hdmi->audio_pdev = platform_device_register_data(1255		dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,1256		&codec_data, sizeof(codec_data));1257 1258	if (IS_ERR(hdmi->audio_pdev))1259		return PTR_ERR(hdmi->audio_pdev);1260 1261	DRM_INFO("%s Driver bound %s\n", HDMI_CODEC_DRV_NAME, dev_name(dev));1262 1263	return 0;1264}1265 1266static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)1267{1268	struct sti_hdmi *hdmi = dev_get_drvdata(dev);1269	struct drm_device *drm_dev = data;1270	struct drm_encoder *encoder;1271	struct sti_hdmi_connector *connector;1272	struct cec_connector_info conn_info;1273	struct drm_connector *drm_connector;1274	struct drm_bridge *bridge;1275	int err;1276 1277	/* Set the drm device handle */1278	hdmi->drm_dev = drm_dev;1279 1280	encoder = sti_hdmi_find_encoder(drm_dev);1281	if (!encoder)1282		return -EINVAL;1283 1284	connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);1285	if (!connector)1286		return -EINVAL;1287 1288	connector->hdmi = hdmi;1289 1290	bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);1291	if (!bridge)1292		return -EINVAL;1293 1294	bridge->driver_private = hdmi;1295	bridge->funcs = &sti_hdmi_bridge_funcs;1296	drm_bridge_attach(encoder, bridge, NULL, 0);1297 1298	connector->encoder = encoder;1299 1300	drm_connector = (struct drm_connector *)connector;1301 1302	drm_connector->polled = DRM_CONNECTOR_POLL_HPD;1303 1304	drm_connector_init_with_ddc(drm_dev, drm_connector,1305				    &sti_hdmi_connector_funcs,1306				    DRM_MODE_CONNECTOR_HDMIA,1307				    hdmi->ddc_adapt);1308	drm_connector_helper_add(drm_connector,1309			&sti_hdmi_connector_helper_funcs);1310 1311	/* initialise property */1312	sti_hdmi_connector_init_property(drm_dev, drm_connector);1313 1314	hdmi->drm_connector = drm_connector;1315 1316	err = drm_connector_attach_encoder(drm_connector, encoder);1317	if (err) {1318		DRM_ERROR("Failed to attach a connector to a encoder\n");1319		goto err_sysfs;1320	}1321 1322	err = sti_hdmi_register_audio_driver(dev, hdmi);1323	if (err) {1324		DRM_ERROR("Failed to attach an audio codec\n");1325		goto err_sysfs;1326	}1327 1328	/* Initialize audio infoframe */1329	err = hdmi_audio_infoframe_init(&hdmi->audio.cea);1330	if (err) {1331		DRM_ERROR("Failed to init audio infoframe\n");1332		goto err_sysfs;1333	}1334 1335	cec_fill_conn_info_from_drm(&conn_info, drm_connector);1336	hdmi->notifier = cec_notifier_conn_register(&hdmi->dev, NULL,1337						    &conn_info);1338	if (!hdmi->notifier) {1339		hdmi->drm_connector = NULL;1340		return -ENOMEM;1341	}1342 1343	/* Enable default interrupts */1344	hdmi_write(hdmi, HDMI_DEFAULT_INT, HDMI_INT_EN);1345 1346	return 0;1347 1348err_sysfs:1349	hdmi->drm_connector = NULL;1350	return -EINVAL;1351}1352 1353static void sti_hdmi_unbind(struct device *dev,1354		struct device *master, void *data)1355{1356	struct sti_hdmi *hdmi = dev_get_drvdata(dev);1357 1358	cec_notifier_conn_unregister(hdmi->notifier);1359}1360 1361static const struct component_ops sti_hdmi_ops = {1362	.bind = sti_hdmi_bind,1363	.unbind = sti_hdmi_unbind,1364};1365 1366static const struct of_device_id hdmi_of_match[] = {1367	{1368		.compatible = "st,stih407-hdmi",1369		.data = &tx3g4c28phy_ops,1370	}, {1371		/* end node */1372	}1373};1374MODULE_DEVICE_TABLE(of, hdmi_of_match);1375 1376static int sti_hdmi_probe(struct platform_device *pdev)1377{1378	struct device *dev = &pdev->dev;1379	struct sti_hdmi *hdmi;1380	struct device_node *np = dev->of_node;1381	struct resource *res;1382	struct device_node *ddc;1383	int ret;1384 1385	DRM_INFO("%s\n", __func__);1386 1387	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);1388	if (!hdmi)1389		return -ENOMEM;1390 1391	ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0);1392	if (ddc) {1393		hdmi->ddc_adapt = of_get_i2c_adapter_by_node(ddc);1394		of_node_put(ddc);1395		if (!hdmi->ddc_adapt)1396			return -EPROBE_DEFER;1397	}1398 1399	hdmi->dev = pdev->dev;1400 1401	/* Get resources */1402	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg");1403	if (!res) {1404		DRM_ERROR("Invalid hdmi resource\n");1405		ret = -ENOMEM;1406		goto release_adapter;1407	}1408	hdmi->regs = devm_ioremap(dev, res->start, resource_size(res));1409	if (!hdmi->regs) {1410		ret = -ENOMEM;1411		goto release_adapter;1412	}1413 1414	hdmi->phy_ops = (struct hdmi_phy_ops *)1415		of_match_node(hdmi_of_match, np)->data;1416 1417	/* Get clock resources */1418	hdmi->clk_pix = devm_clk_get(dev, "pix");1419	if (IS_ERR(hdmi->clk_pix)) {1420		DRM_ERROR("Cannot get hdmi_pix clock\n");1421		ret = PTR_ERR(hdmi->clk_pix);1422		goto release_adapter;1423	}1424 1425	hdmi->clk_tmds = devm_clk_get(dev, "tmds");1426	if (IS_ERR(hdmi->clk_tmds)) {1427		DRM_ERROR("Cannot get hdmi_tmds clock\n");1428		ret = PTR_ERR(hdmi->clk_tmds);1429		goto release_adapter;1430	}1431 1432	hdmi->clk_phy = devm_clk_get(dev, "phy");1433	if (IS_ERR(hdmi->clk_phy)) {1434		DRM_ERROR("Cannot get hdmi_phy clock\n");1435		ret = PTR_ERR(hdmi->clk_phy);1436		goto release_adapter;1437	}1438 1439	hdmi->clk_audio = devm_clk_get(dev, "audio");1440	if (IS_ERR(hdmi->clk_audio)) {1441		DRM_ERROR("Cannot get hdmi_audio clock\n");1442		ret = PTR_ERR(hdmi->clk_audio);1443		goto release_adapter;1444	}1445 1446	hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG;1447 1448	init_waitqueue_head(&hdmi->wait_event);1449 1450	hdmi->irq = platform_get_irq_byname(pdev, "irq");1451	if (hdmi->irq < 0) {1452		DRM_ERROR("Cannot get HDMI irq\n");1453		ret = hdmi->irq;1454		goto release_adapter;1455	}1456 1457	ret = devm_request_threaded_irq(dev, hdmi->irq, hdmi_irq,1458			hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi);1459	if (ret) {1460		DRM_ERROR("Failed to register HDMI interrupt\n");1461		goto release_adapter;1462	}1463 1464	hdmi->reset = devm_reset_control_get(dev, "hdmi");1465	/* Take hdmi out of reset */1466	if (!IS_ERR(hdmi->reset))1467		reset_control_deassert(hdmi->reset);1468 1469	platform_set_drvdata(pdev, hdmi);1470 1471	return component_add(&pdev->dev, &sti_hdmi_ops);1472 1473 release_adapter:1474	i2c_put_adapter(hdmi->ddc_adapt);1475 1476	return ret;1477}1478 1479static void sti_hdmi_remove(struct platform_device *pdev)1480{1481	struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);1482 1483	i2c_put_adapter(hdmi->ddc_adapt);1484	if (hdmi->audio_pdev)1485		platform_device_unregister(hdmi->audio_pdev);1486	component_del(&pdev->dev, &sti_hdmi_ops);1487}1488 1489struct platform_driver sti_hdmi_driver = {1490	.driver = {1491		.name = "sti-hdmi",1492		.of_match_table = hdmi_of_match,1493	},1494	.probe = sti_hdmi_probe,1495	.remove_new = sti_hdmi_remove,1496};1497 1498MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");1499MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");1500MODULE_LICENSE("GPL");1501