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 = ¶ms->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