^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2018 Renesas Electronics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2016 Atmel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Bo Shen <voice.shen@atmel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Authors: Bo Shen <voice.shen@atmel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Boris Brezillon <boris.brezillon@free-electrons.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Wu, Songjun <Songjun.Wu@atmel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/i2c-mux.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <drm/drm_atomic_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <drm/drm_bridge.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <drm/drm_drv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <drm/drm_edid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <drm/drm_modes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <drm/drm_print.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <drm/drm_probe_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <sound/hdmi-codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <video/videomode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define SII902X_TPI_VIDEO_DATA 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define SII902X_TPI_PIXEL_REPETITION 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define SII902X_TPI_AVI_PIXEL_REP_BUS_24BIT BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define SII902X_TPI_AVI_PIXEL_REP_RISING_EDGE BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define SII902X_TPI_AVI_PIXEL_REP_4X 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define SII902X_TPI_AVI_PIXEL_REP_2X 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define SII902X_TPI_AVI_PIXEL_REP_NONE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define SII902X_TPI_CLK_RATIO_HALF (0 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define SII902X_TPI_CLK_RATIO_1X (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define SII902X_TPI_CLK_RATIO_2X (2 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define SII902X_TPI_CLK_RATIO_4X (3 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SII902X_TPI_AVI_IN_FORMAT 0x9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SII902X_TPI_AVI_INPUT_BITMODE_12BIT BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SII902X_TPI_AVI_INPUT_DITHER BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define SII902X_TPI_AVI_INPUT_RANGE_LIMITED (2 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define SII902X_TPI_AVI_INPUT_RANGE_FULL (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define SII902X_TPI_AVI_INPUT_RANGE_AUTO (0 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define SII902X_TPI_AVI_INPUT_COLORSPACE_BLACK (3 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define SII902X_TPI_AVI_INPUT_COLORSPACE_YUV422 (2 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define SII902X_TPI_AVI_INPUT_COLORSPACE_YUV444 (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define SII902X_TPI_AVI_INPUT_COLORSPACE_RGB (0 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define SII902X_TPI_AVI_INFOFRAME 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define SII902X_SYS_CTRL_DATA 0x1a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define SII902X_SYS_CTRL_PWR_DWN BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define SII902X_SYS_CTRL_AV_MUTE BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define SII902X_SYS_CTRL_DDC_BUS_REQ BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define SII902X_SYS_CTRL_DDC_BUS_GRTD BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define SII902X_SYS_CTRL_OUTPUT_MODE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define SII902X_SYS_CTRL_OUTPUT_HDMI 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define SII902X_SYS_CTRL_OUTPUT_DVI 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define SII902X_REG_CHIPID(n) (0x1b + (n))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define SII902X_PWR_STATE_CTRL 0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define SII902X_AVI_POWER_STATE_MSK GENMASK(1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define SII902X_AVI_POWER_STATE_D(l) ((l) & SII902X_AVI_POWER_STATE_MSK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* Audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define SII902X_TPI_I2S_ENABLE_MAPPING_REG 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define SII902X_TPI_I2S_CONFIG_FIFO0 (0 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define SII902X_TPI_I2S_CONFIG_FIFO1 (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define SII902X_TPI_I2S_CONFIG_FIFO2 (2 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define SII902X_TPI_I2S_CONFIG_FIFO3 (3 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define SII902X_TPI_I2S_LEFT_RIGHT_SWAP (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define SII902X_TPI_I2S_AUTO_DOWNSAMPLE (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define SII902X_TPI_I2S_SELECT_SD0 (0 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define SII902X_TPI_I2S_SELECT_SD1 (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define SII902X_TPI_I2S_SELECT_SD2 (2 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define SII902X_TPI_I2S_SELECT_SD3 (3 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define SII902X_TPI_I2S_FIFO_ENABLE (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define SII902X_TPI_I2S_INPUT_CONFIG_REG 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define SII902X_TPI_I2S_FIRST_BIT_SHIFT_YES (0 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define SII902X_TPI_I2S_FIRST_BIT_SHIFT_NO (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define SII902X_TPI_I2S_SD_DIRECTION_MSB_FIRST (0 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define SII902X_TPI_I2S_SD_DIRECTION_LSB_FIRST (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define SII902X_TPI_I2S_SD_JUSTIFY_LEFT (0 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define SII902X_TPI_I2S_SD_JUSTIFY_RIGHT (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define SII902X_TPI_I2S_WS_POLARITY_LOW (0 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define SII902X_TPI_I2S_WS_POLARITY_HIGH (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define SII902X_TPI_I2S_MCLK_MULTIPLIER_128 (0 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define SII902X_TPI_I2S_MCLK_MULTIPLIER_256 (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define SII902X_TPI_I2S_MCLK_MULTIPLIER_384 (2 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define SII902X_TPI_I2S_MCLK_MULTIPLIER_512 (3 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define SII902X_TPI_I2S_MCLK_MULTIPLIER_768 (4 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define SII902X_TPI_I2S_MCLK_MULTIPLIER_1024 (5 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define SII902X_TPI_I2S_MCLK_MULTIPLIER_1152 (6 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define SII902X_TPI_I2S_MCLK_MULTIPLIER_192 (7 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define SII902X_TPI_I2S_SCK_EDGE_FALLING (0 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define SII902X_TPI_I2S_SCK_EDGE_RISING (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define SII902X_TPI_I2S_STRM_HDR_BASE 0x21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define SII902X_TPI_I2S_STRM_HDR_SIZE 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define SII902X_TPI_AUDIO_CONFIG_BYTE2_REG 0x26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define SII902X_TPI_AUDIO_CODING_STREAM_HEADER (0 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define SII902X_TPI_AUDIO_CODING_PCM (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define SII902X_TPI_AUDIO_CODING_AC3 (2 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define SII902X_TPI_AUDIO_CODING_MPEG1 (3 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define SII902X_TPI_AUDIO_CODING_MP3 (4 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define SII902X_TPI_AUDIO_CODING_MPEG2 (5 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define SII902X_TPI_AUDIO_CODING_AAC (6 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define SII902X_TPI_AUDIO_CODING_DTS (7 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define SII902X_TPI_AUDIO_CODING_ATRAC (8 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define SII902X_TPI_AUDIO_MUTE_DISABLE (0 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define SII902X_TPI_AUDIO_MUTE_ENABLE (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define SII902X_TPI_AUDIO_LAYOUT_2_CHANNELS (0 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define SII902X_TPI_AUDIO_LAYOUT_8_CHANNELS (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define SII902X_TPI_AUDIO_INTERFACE_DISABLE (0 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define SII902X_TPI_AUDIO_INTERFACE_SPDIF (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define SII902X_TPI_AUDIO_INTERFACE_I2S (2 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define SII902X_TPI_AUDIO_CONFIG_BYTE3_REG 0x27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define SII902X_TPI_AUDIO_FREQ_STREAM (0 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define SII902X_TPI_AUDIO_FREQ_32KHZ (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define SII902X_TPI_AUDIO_FREQ_44KHZ (2 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define SII902X_TPI_AUDIO_FREQ_48KHZ (3 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define SII902X_TPI_AUDIO_FREQ_88KHZ (4 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define SII902X_TPI_AUDIO_FREQ_96KHZ (5 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define SII902X_TPI_AUDIO_FREQ_176KHZ (6 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define SII902X_TPI_AUDIO_FREQ_192KHZ (7 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define SII902X_TPI_AUDIO_SAMPLE_SIZE_STREAM (0 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define SII902X_TPI_AUDIO_SAMPLE_SIZE_16 (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define SII902X_TPI_AUDIO_SAMPLE_SIZE_20 (2 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define SII902X_TPI_AUDIO_SAMPLE_SIZE_24 (3 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define SII902X_TPI_AUDIO_CONFIG_BYTE4_REG 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define SII902X_INT_ENABLE 0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define SII902X_INT_STATUS 0x3d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define SII902X_HOTPLUG_EVENT BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define SII902X_PLUGGED_STATUS BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define SII902X_TPI_SYNC_GEN_CTRL 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define SII902X_TPI_SYNC_POLAR_DETECT 0x61
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define SII902X_TPI_HBIT_TO_HSYNC 0x62
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define SII902X_EMBEDDED_SYNC_EXTRACTION_REG 0x63
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define SII902X_EMBEDDED_SYNC_EXTRACTION BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define SII902X_REG_TPI_RQB 0xc7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* Indirect internal register access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define SII902X_IND_SET_PAGE 0xbc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define SII902X_IND_OFFSET 0xbd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define SII902X_IND_VALUE 0xbe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define SII902X_TPI_MISC_INFOFRAME_BASE 0xbf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define SII902X_TPI_MISC_INFOFRAME_END 0xde
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define SII902X_TPI_MISC_INFOFRAME_SIZE \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) (SII902X_TPI_MISC_INFOFRAME_END - SII902X_TPI_MISC_INFOFRAME_BASE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define SII902X_AUDIO_PORT_INDEX 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct sii902x {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct i2c_client *i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct drm_bridge bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct drm_connector connector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct gpio_desc *reset_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct gpio_desc *enable_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct i2c_mux_core *i2cmux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct regulator_bulk_data supplies[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * Mutex protects audio and video functions from interfering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * each other, by keeping their i2c command sequences atomic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct mutex mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct sii902x_audio {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct clk *mclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) u32 i2s_fifo_sequence[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) } audio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct drm_display_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int bus_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) enum sii902x_bus_format {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) FORMAT_RGB_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) FORMAT_YCBCR422_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) FORMAT_YCBCR444_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static int sii902x_read_unlocked(struct i2c_client *i2c, u8 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) union i2c_smbus_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ret = __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) *val = data.byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int sii902x_write_unlocked(struct i2c_client *i2c, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) union i2c_smbus_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) data.byte = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static int sii902x_update_bits_unlocked(struct i2c_client *i2c, u8 reg, u8 mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ret = sii902x_read_unlocked(i2c, reg, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) status &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) status |= val & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return sii902x_write_unlocked(i2c, reg, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static inline struct sii902x *bridge_to_sii902x(struct drm_bridge *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return container_of(bridge, struct sii902x, bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static inline struct sii902x *connector_to_sii902x(struct drm_connector *con)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return container_of(con, struct sii902x, connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static void sii902x_reset(struct sii902x *sii902x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (!sii902x->reset_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) gpiod_set_value(sii902x->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* The datasheet says treset-min = 100us. Make it 150us to be sure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) usleep_range(150, 200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) gpiod_set_value(sii902x->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static enum drm_connector_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) sii902x_connector_detect(struct drm_connector *connector, bool force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct sii902x *sii902x = connector_to_sii902x(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) mutex_lock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) mutex_unlock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return (status & SII902X_PLUGGED_STATUS) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) connector_status_connected : connector_status_disconnected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static const struct drm_connector_funcs sii902x_connector_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .detect = sii902x_connector_detect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .fill_modes = drm_helper_probe_single_connector_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .destroy = drm_connector_cleanup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .reset = drm_atomic_helper_connector_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static const struct drm_display_mode sii902x_default_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* 4 - 1280x720@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 1430, 1650, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* 16 - 1920x1080@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* 5 - 1920x1080i@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) DRM_MODE_FLAG_INTERLACE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /* 31 - 1920x1080@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* 19 - 1280x720@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 1760, 1980, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* 0x10 - 1024x768@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 1184, 1344, 0, 768, 771, 777, 806, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /* 17 - 720x576@50Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 796, 864, 0, 576, 581, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* 2 - 720x480@60Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 798, 858, 0, 480, 489, 495, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int sii902x_get_modes(struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct sii902x *sii902x = connector_to_sii902x(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) u8 output_mode = SII902X_SYS_CTRL_OUTPUT_DVI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct edid *edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int num = 0, ret = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) mutex_lock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) drm_connector_update_edid_property(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (edid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (drm_detect_hdmi_monitor(edid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) num = drm_add_edid_modes(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) kfree(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) for (i = 0; i < ARRAY_SIZE(sii902x_default_modes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) const struct drm_display_mode *ptr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) &sii902x_default_modes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) mode = drm_mode_duplicate(connector->dev, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) mode->type = DRM_MODE_TYPE_PREFERRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) drm_mode_probed_add(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) ret++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ret = drm_display_info_set_bus_formats(&connector->display_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) &sii902x->bus_format, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) ret = regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) SII902X_SYS_CTRL_OUTPUT_MODE, output_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) ret = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) mutex_unlock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static enum drm_mode_status sii902x_mode_valid(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (mode->hdisplay > 1920 || mode->vdisplay > 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return MODE_BAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (mode->clock > 165000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return MODE_BAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return MODE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static const struct drm_connector_helper_funcs sii902x_connector_helper_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) .get_modes = sii902x_get_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) .mode_valid = sii902x_mode_valid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static void sii902x_bridge_disable(struct drm_bridge *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct sii902x *sii902x = bridge_to_sii902x(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) mutex_lock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) SII902X_SYS_CTRL_PWR_DWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) SII902X_SYS_CTRL_PWR_DWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) mutex_unlock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) static void sii902x_bridge_enable(struct drm_bridge *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct sii902x *sii902x = bridge_to_sii902x(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) mutex_lock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) regmap_update_bits(sii902x->regmap, SII902X_PWR_STATE_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) SII902X_AVI_POWER_STATE_MSK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) SII902X_AVI_POWER_STATE_D(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) SII902X_SYS_CTRL_PWR_DWN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) mutex_unlock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) static bool sii902x_check_embedded_format(uint32_t bus_format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) switch (bus_format) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) case MEDIA_BUS_FMT_YUYV8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) case MEDIA_BUS_FMT_YVYU8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) case MEDIA_BUS_FMT_UYVY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) case MEDIA_BUS_FMT_VYUY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) case MEDIA_BUS_FMT_YUYV8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) case MEDIA_BUS_FMT_YVYU8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) case MEDIA_BUS_FMT_UYVY8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) case MEDIA_BUS_FMT_VYUY8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static void sii902x_set_embedded_sync(struct sii902x *sii902x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) unsigned char data[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct videomode vm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (!sii902x_check_embedded_format(sii902x->bus_format))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) switch (sii902x->bus_format) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) case MEDIA_BUS_FMT_YUYV8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) case MEDIA_BUS_FMT_YVYU8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) case MEDIA_BUS_FMT_UYVY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) case MEDIA_BUS_FMT_VYUY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) sii902x_update_bits_unlocked(sii902x->i2c, SII902X_TPI_SYNC_GEN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) sii902x_update_bits_unlocked(sii902x->i2c, SII902X_TPI_SYNC_GEN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 0x80, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) regmap_write(sii902x->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) SII902X_EMBEDDED_SYNC_EXTRACTION_REG, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) sii902x_update_bits_unlocked(sii902x->i2c, SII902X_TPI_SYNC_GEN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) drm_display_mode_to_videomode(&sii902x->mode, &vm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) data[0] = vm.hfront_porch & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) data[1] = (vm.hfront_porch >> 8) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) data[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) data[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) data[4] = vm.hsync_len & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) data[5] = (vm.hsync_len >> 8) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) data[6] = vm.vfront_porch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) data[7] = vm.vsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) regmap_bulk_write(sii902x->regmap, SII902X_TPI_HBIT_TO_HSYNC, data, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) sii902x_update_bits_unlocked(sii902x->i2c, SII902X_TPI_SYNC_GEN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) sii902x_update_bits_unlocked(sii902x->i2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) SII902X_EMBEDDED_SYNC_EXTRACTION_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 0x40, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) regmap_update_bits(sii902x->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) SII902X_EMBEDDED_SYNC_EXTRACTION_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) SII902X_EMBEDDED_SYNC_EXTRACTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) SII902X_EMBEDDED_SYNC_EXTRACTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static void sii902x_set_format(struct sii902x *sii902x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) switch (sii902x->bus_format) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) case MEDIA_BUS_FMT_YUYV8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) case MEDIA_BUS_FMT_YVYU8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) case MEDIA_BUS_FMT_UYVY8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) case MEDIA_BUS_FMT_VYUY8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) case MEDIA_BUS_FMT_YUYV8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) case MEDIA_BUS_FMT_YVYU8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) case MEDIA_BUS_FMT_UYVY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) case MEDIA_BUS_FMT_VYUY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) val = SII902X_TPI_AVI_INPUT_COLORSPACE_YUV422;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) case MEDIA_BUS_FMT_YUV8_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) case MEDIA_BUS_FMT_VUY8_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) val = SII902X_TPI_AVI_INPUT_COLORSPACE_YUV444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) case MEDIA_BUS_FMT_RGB888_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) val = SII902X_TPI_AVI_INPUT_COLORSPACE_RGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) val |= SII902X_TPI_AVI_INPUT_RANGE_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) val &= ~(SII902X_TPI_AVI_INPUT_DITHER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) SII902X_TPI_AVI_INPUT_BITMODE_12BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) regmap_write(sii902x->regmap, SII902X_TPI_AVI_IN_FORMAT, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) sii902x_set_embedded_sync(sii902x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) const struct drm_display_mode *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) const struct drm_display_mode *adj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct sii902x *sii902x = bridge_to_sii902x(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct regmap *regmap = sii902x->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct hdmi_avi_infoframe frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) u16 pixel_clock_10kHz = adj->clock / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) int ret, vrefresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) drm_mode_copy(&sii902x->mode, adj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) vrefresh = drm_mode_vrefresh(mode) * 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) buf[0] = pixel_clock_10kHz & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) buf[1] = pixel_clock_10kHz >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) buf[2] = vrefresh & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) buf[3] = vrefresh >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) buf[4] = adj->crtc_htotal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) buf[5] = adj->crtc_htotal >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) buf[6] = adj->crtc_vtotal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) buf[7] = adj->crtc_vtotal >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) buf[8] = SII902X_TPI_CLK_RATIO_1X | SII902X_TPI_AVI_PIXEL_REP_NONE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) SII902X_TPI_AVI_PIXEL_REP_BUS_24BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) switch (sii902x->bus_format) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) case MEDIA_BUS_FMT_YUYV8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) case MEDIA_BUS_FMT_YVYU8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) case MEDIA_BUS_FMT_UYVY8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) case MEDIA_BUS_FMT_VYUY8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) case MEDIA_BUS_FMT_YUYV8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) case MEDIA_BUS_FMT_YVYU8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) case MEDIA_BUS_FMT_UYVY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) case MEDIA_BUS_FMT_VYUY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) buf[8] |= SII902X_TPI_AVI_PIXEL_REP_RISING_EDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) buf[9] = SII902X_TPI_AVI_INPUT_RANGE_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) switch (sii902x->bus_format) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) case MEDIA_BUS_FMT_YUYV8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) case MEDIA_BUS_FMT_YVYU8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) case MEDIA_BUS_FMT_UYVY8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) case MEDIA_BUS_FMT_VYUY8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) case MEDIA_BUS_FMT_YUYV8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) case MEDIA_BUS_FMT_YVYU8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) case MEDIA_BUS_FMT_UYVY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) case MEDIA_BUS_FMT_VYUY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) buf[9] |= SII902X_TPI_AVI_INPUT_COLORSPACE_YUV422;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) case MEDIA_BUS_FMT_YUV8_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) case MEDIA_BUS_FMT_VUY8_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) buf[9] |= SII902X_TPI_AVI_INPUT_COLORSPACE_YUV444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) case MEDIA_BUS_FMT_RGB888_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) buf[9] |= SII902X_TPI_AVI_INPUT_COLORSPACE_RGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) mutex_lock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) ret = regmap_bulk_write(regmap, SII902X_TPI_VIDEO_DATA, buf, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) ret = drm_hdmi_avi_infoframe_from_display_mode(&frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) &sii902x->connector, adj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) DRM_ERROR("couldn't fill AVI infoframe\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) ret = hdmi_avi_infoframe_pack(&frame, buf, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) DRM_ERROR("failed to pack AVI infoframe: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /* Do not send the infoframe header, but keep the CRC field. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) regmap_bulk_write(regmap, SII902X_TPI_AVI_INFOFRAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) buf + HDMI_INFOFRAME_HEADER_SIZE - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) HDMI_AVI_INFOFRAME_SIZE + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) sii902x_set_format(sii902x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) mutex_unlock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static int sii902x_bridge_attach(struct drm_bridge *bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) enum drm_bridge_attach_flags flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) struct sii902x *sii902x = bridge_to_sii902x(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct drm_device *drm = bridge->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) DRM_ERROR("Fix bridge driver to make connector optional!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) sii902x->connector.interlace_allowed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) drm_connector_helper_add(&sii902x->connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) &sii902x_connector_helper_funcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (!drm_core_check_feature(drm, DRIVER_ATOMIC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) dev_err(&sii902x->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) "sii902x driver is only compatible with DRM devices supporting atomic updates\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) ret = drm_connector_init(drm, &sii902x->connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) &sii902x_connector_funcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) DRM_MODE_CONNECTOR_HDMIA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (sii902x->i2c->irq > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) sii902x->connector.polled = DRM_CONNECTOR_POLL_HPD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) sii902x->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) drm_connector_attach_encoder(&sii902x->connector, bridge->encoder);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static const struct drm_bridge_funcs sii902x_bridge_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) .attach = sii902x_bridge_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) .mode_set = sii902x_bridge_mode_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) .disable = sii902x_bridge_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) .enable = sii902x_bridge_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) static int sii902x_mute(struct sii902x *sii902x, bool mute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct device *dev = &sii902x->i2c->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) unsigned int val = mute ? SII902X_TPI_AUDIO_MUTE_ENABLE :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) SII902X_TPI_AUDIO_MUTE_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) dev_dbg(dev, "%s: %s\n", __func__, mute ? "Muted" : "Unmuted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return regmap_update_bits(sii902x->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) SII902X_TPI_AUDIO_CONFIG_BYTE2_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) SII902X_TPI_AUDIO_MUTE_ENABLE, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) static const int sii902x_mclk_div_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 128, 256, 384, 512, 768, 1024, 1152, 192 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) static int sii902x_select_mclk_div(u8 *i2s_config_reg, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) unsigned int mclk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) int div = mclk / rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) int distance = 100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) u8 i, nearest = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) for (i = 0; i < ARRAY_SIZE(sii902x_mclk_div_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) unsigned int d = abs(div - sii902x_mclk_div_table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (d >= distance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) nearest = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) distance = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (d == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) *i2s_config_reg |= nearest << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) return sii902x_mclk_div_table[nearest];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) static const struct sii902x_sample_freq {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) u32 freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) } sii902x_sample_freq[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) { .freq = 32000, .val = SII902X_TPI_AUDIO_FREQ_32KHZ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) { .freq = 44000, .val = SII902X_TPI_AUDIO_FREQ_44KHZ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) { .freq = 48000, .val = SII902X_TPI_AUDIO_FREQ_48KHZ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) { .freq = 88000, .val = SII902X_TPI_AUDIO_FREQ_88KHZ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) { .freq = 96000, .val = SII902X_TPI_AUDIO_FREQ_96KHZ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) { .freq = 176000, .val = SII902X_TPI_AUDIO_FREQ_176KHZ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) { .freq = 192000, .val = SII902X_TPI_AUDIO_FREQ_192KHZ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static int sii902x_audio_hw_params(struct device *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) struct hdmi_codec_daifmt *daifmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct hdmi_codec_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct sii902x *sii902x = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) u8 i2s_config_reg = SII902X_TPI_I2S_SD_DIRECTION_MSB_FIRST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) u8 config_byte2_reg = (SII902X_TPI_AUDIO_INTERFACE_I2S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) SII902X_TPI_AUDIO_MUTE_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) SII902X_TPI_AUDIO_CODING_PCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) u8 config_byte3_reg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) u8 infoframe_buf[HDMI_INFOFRAME_SIZE(AUDIO)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) unsigned long mclk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (daifmt->bit_clk_master || daifmt->frame_clk_master) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) dev_dbg(dev, "%s: I2S master mode not supported\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) switch (daifmt->fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) case HDMI_I2S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) i2s_config_reg |= SII902X_TPI_I2S_FIRST_BIT_SHIFT_YES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) SII902X_TPI_I2S_SD_JUSTIFY_LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) case HDMI_RIGHT_J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) i2s_config_reg |= SII902X_TPI_I2S_SD_JUSTIFY_RIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) case HDMI_LEFT_J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) i2s_config_reg |= SII902X_TPI_I2S_SD_JUSTIFY_LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) dev_dbg(dev, "%s: Unsupported i2s format %u\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) daifmt->fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (daifmt->bit_clk_inv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) i2s_config_reg |= SII902X_TPI_I2S_SCK_EDGE_FALLING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) i2s_config_reg |= SII902X_TPI_I2S_SCK_EDGE_RISING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (daifmt->frame_clk_inv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) i2s_config_reg |= SII902X_TPI_I2S_WS_POLARITY_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) i2s_config_reg |= SII902X_TPI_I2S_WS_POLARITY_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (params->channels > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) config_byte2_reg |= SII902X_TPI_AUDIO_LAYOUT_8_CHANNELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) config_byte2_reg |= SII902X_TPI_AUDIO_LAYOUT_2_CHANNELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) switch (params->sample_width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) config_byte3_reg |= SII902X_TPI_AUDIO_SAMPLE_SIZE_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) case 20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) config_byte3_reg |= SII902X_TPI_AUDIO_SAMPLE_SIZE_20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) config_byte3_reg |= SII902X_TPI_AUDIO_SAMPLE_SIZE_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) dev_err(dev, "%s: Unsupported sample width %u\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) params->sample_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) for (i = 0; i < ARRAY_SIZE(sii902x_sample_freq); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (params->sample_rate == sii902x_sample_freq[i].freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) config_byte3_reg |= sii902x_sample_freq[i].val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) ret = clk_prepare_enable(sii902x->audio.mclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) dev_err(dev, "Enabling mclk failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (sii902x->audio.mclk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) mclk_rate = clk_get_rate(sii902x->audio.mclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) ret = sii902x_select_mclk_div(&i2s_config_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) params->sample_rate, mclk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (mclk_rate != ret * params->sample_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) dev_dbg(dev, "Inaccurate reference clock (%ld/%d != %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) mclk_rate, ret, params->sample_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) mutex_lock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) ret = regmap_write(sii902x->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) SII902X_TPI_AUDIO_CONFIG_BYTE2_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) config_byte2_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) ret = regmap_write(sii902x->regmap, SII902X_TPI_I2S_INPUT_CONFIG_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) i2s_config_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) for (i = 0; i < ARRAY_SIZE(sii902x->audio.i2s_fifo_sequence) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) sii902x->audio.i2s_fifo_sequence[i]; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) regmap_write(sii902x->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) SII902X_TPI_I2S_ENABLE_MAPPING_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) sii902x->audio.i2s_fifo_sequence[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ret = regmap_write(sii902x->regmap, SII902X_TPI_AUDIO_CONFIG_BYTE3_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) config_byte3_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) ret = regmap_bulk_write(sii902x->regmap, SII902X_TPI_I2S_STRM_HDR_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) params->iec.status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) min((size_t) SII902X_TPI_I2S_STRM_HDR_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) sizeof(params->iec.status)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) ret = hdmi_audio_infoframe_pack(¶ms->cea, infoframe_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) sizeof(infoframe_buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) dev_err(dev, "%s: Failed to pack audio infoframe: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) ret = regmap_bulk_write(sii902x->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) SII902X_TPI_MISC_INFOFRAME_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) infoframe_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) min(ret, SII902X_TPI_MISC_INFOFRAME_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /* Decode Level 0 Packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) ret = regmap_write(sii902x->regmap, SII902X_IND_SET_PAGE, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) ret = regmap_write(sii902x->regmap, SII902X_IND_OFFSET, 0x24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) ret = regmap_write(sii902x->regmap, SII902X_IND_VALUE, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) dev_dbg(dev, "%s: hdmi audio enabled\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) mutex_unlock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) clk_disable_unprepare(sii902x->audio.mclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) dev_err(dev, "%s: hdmi audio enable failed: %d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) static void sii902x_audio_shutdown(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) struct sii902x *sii902x = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) mutex_lock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) regmap_write(sii902x->regmap, SII902X_TPI_AUDIO_CONFIG_BYTE2_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) SII902X_TPI_AUDIO_INTERFACE_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) mutex_unlock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) clk_disable_unprepare(sii902x->audio.mclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static int sii902x_audio_mute(struct device *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) bool enable, int direction)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct sii902x *sii902x = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) mutex_lock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) sii902x_mute(sii902x, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) mutex_unlock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) static int sii902x_audio_get_eld(struct device *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) uint8_t *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) struct sii902x *sii902x = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) mutex_lock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) memcpy(buf, sii902x->connector.eld,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) min(sizeof(sii902x->connector.eld), len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) mutex_unlock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static int sii902x_audio_get_dai_id(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct device_node *endpoint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct of_endpoint of_ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) ret = of_graph_parse_endpoint(endpoint, &of_ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * HDMI sound should be located at reg = <3>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) * Return expected DAI index 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (of_ep.port == SII902X_AUDIO_PORT_INDEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) static const struct hdmi_codec_ops sii902x_audio_codec_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .hw_params = sii902x_audio_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) .audio_shutdown = sii902x_audio_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) .mute_stream = sii902x_audio_mute,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) .get_eld = sii902x_audio_get_eld,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) .get_dai_id = sii902x_audio_get_dai_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) .no_capture_mute = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) static int sii902x_audio_codec_init(struct sii902x *sii902x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) static const u8 audio_fifo_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) SII902X_TPI_I2S_CONFIG_FIFO0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) SII902X_TPI_I2S_CONFIG_FIFO1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) SII902X_TPI_I2S_CONFIG_FIFO2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) SII902X_TPI_I2S_CONFIG_FIFO3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) static const u8 i2s_lane_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) SII902X_TPI_I2S_SELECT_SD0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) SII902X_TPI_I2S_SELECT_SD1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) SII902X_TPI_I2S_SELECT_SD2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) SII902X_TPI_I2S_SELECT_SD3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) struct hdmi_codec_pdata codec_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) .ops = &sii902x_audio_codec_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) .i2s = 1, /* Only i2s support for now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) .spdif = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) .max_i2s_channels = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) u8 lanes[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) int num_lanes, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (!of_property_read_bool(dev->of_node, "#sound-dai-cells")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) dev_dbg(dev, "%s: No \"#sound-dai-cells\", no audio\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) num_lanes = of_property_read_variable_u8_array(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) "sil,i2s-data-lanes",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) lanes, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) ARRAY_SIZE(lanes));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (num_lanes == -EINVAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) dev_dbg(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) "%s: No \"sil,i2s-data-lanes\", use default <0>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) num_lanes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) lanes[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) } else if (num_lanes < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) "%s: Error gettin \"sil,i2s-data-lanes\": %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) __func__, num_lanes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return num_lanes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) codec_data.max_i2s_channels = 2 * num_lanes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) for (i = 0; i < num_lanes; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) sii902x->audio.i2s_fifo_sequence[i] |= audio_fifo_id[i] |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) i2s_lane_id[lanes[i]] | SII902X_TPI_I2S_FIFO_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) sii902x->audio.mclk = devm_clk_get_optional(dev, "mclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (IS_ERR(sii902x->audio.mclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) dev_err(dev, "%s: No clock (audio mclk) found: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) __func__, PTR_ERR(sii902x->audio.mclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return PTR_ERR(sii902x->audio.mclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) sii902x->audio.pdev = platform_device_register_data(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) &codec_data, sizeof(codec_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) return PTR_ERR_OR_ZERO(sii902x->audio.pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) static const struct regmap_range sii902x_volatile_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) { .range_min = 0, .range_max = 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) static const struct regmap_access_table sii902x_volatile_table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) .yes_ranges = sii902x_volatile_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) .n_yes_ranges = ARRAY_SIZE(sii902x_volatile_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) static const struct regmap_config sii902x_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) .disable_locking = true, /* struct sii902x mutex should be enough */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) .max_register = SII902X_TPI_MISC_INFOFRAME_END,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) .volatile_table = &sii902x_volatile_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) static irqreturn_t sii902x_interrupt(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) struct sii902x *sii902x = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) unsigned int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) mutex_lock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) regmap_write(sii902x->regmap, SII902X_INT_STATUS, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) mutex_unlock(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if ((status & SII902X_HOTPLUG_EVENT) && sii902x->bridge.dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) drm_helper_hpd_irq_event(sii902x->bridge.dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) * The purpose of sii902x_i2c_bypass_select is to enable the pass through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) * mode of the HDMI transmitter. Do not use regmap from within this function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) * only use sii902x_*_unlocked functions to read/modify/write registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) * We are holding the parent adapter lock here, keep this in mind before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) * adding more i2c transactions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * Also, since SII902X_SYS_CTRL_DATA is used with regmap_update_bits elsewhere
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) * in this driver, we need to make sure that we only touch 0x1A[2:1] from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * within sii902x_i2c_bypass_select and sii902x_i2c_bypass_deselect, and that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * we leave the remaining bits as we have found them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static int sii902x_i2c_bypass_select(struct i2c_mux_core *mux, u32 chan_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct sii902x *sii902x = i2c_mux_priv(mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct device *dev = &sii902x->i2c->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) ret = sii902x_update_bits_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) SII902X_SYS_CTRL_DDC_BUS_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) SII902X_SYS_CTRL_DDC_BUS_REQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) timeout = jiffies +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) } while (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) time_before(jiffies, timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) dev_err(dev, "Failed to acquire the i2c bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return sii902x_write_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * The purpose of sii902x_i2c_bypass_deselect is to disable the pass through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) * mode of the HDMI transmitter. Do not use regmap from within this function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) * only use sii902x_*_unlocked functions to read/modify/write registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) * We are holding the parent adapter lock here, keep this in mind before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) * adding more i2c transactions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * Also, since SII902X_SYS_CTRL_DATA is used with regmap_update_bits elsewhere
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) * in this driver, we need to make sure that we only touch 0x1A[2:1] from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * within sii902x_i2c_bypass_select and sii902x_i2c_bypass_deselect, and that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * we leave the remaining bits as we have found them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) static int sii902x_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) struct sii902x *sii902x = i2c_mux_priv(mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) struct device *dev = &sii902x->i2c->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) unsigned int retries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) * When the HDMI transmitter is in pass through mode, we need an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) * (undocumented) additional delay between STOP and START conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) * to guarantee the bus won't get stuck.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) udelay(30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) * Sometimes the I2C bus can stall after failure to use the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) * EDID channel. Retry a few times to see if things clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) * up, else continue anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) retries = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) retries--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) } while (ret && retries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) dev_err(dev, "failed to read status (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) ret = sii902x_update_bits_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) SII902X_SYS_CTRL_DDC_BUS_REQ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) SII902X_SYS_CTRL_DDC_BUS_GRTD, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) timeout = jiffies +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) } while (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) time_before(jiffies, timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) dev_err(dev, "failed to release the i2c bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) static const struct drm_bridge_timings default_sii902x_timings = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) .input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) | DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) | DRM_BUS_FLAG_DE_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) static int sii902x_init(struct sii902x *sii902x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) struct device *dev = &sii902x->i2c->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) unsigned int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) u8 chipid[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) sii902x_reset(sii902x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) ret = regmap_write(sii902x->regmap, SII902X_REG_TPI_RQB, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) dev_err(dev, "enable TPI mode failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) ret = regmap_bulk_read(sii902x->regmap, SII902X_REG_CHIPID(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) &chipid, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) dev_err(dev, "regmap_read failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (chipid[0] != 0xb0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) dev_err(dev, "Invalid chipid: %02x (expecting 0xb0)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) chipid[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) /* Clear all pending interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) regmap_write(sii902x->regmap, SII902X_INT_STATUS, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (sii902x->i2c->irq > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) regmap_write(sii902x->regmap, SII902X_INT_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) SII902X_HOTPLUG_EVENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) ret = devm_request_threaded_irq(dev, sii902x->i2c->irq, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) sii902x_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) IRQF_TRIGGER_FALLING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) IRQF_ONESHOT, dev_name(dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) sii902x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) sii902x->bridge.funcs = &sii902x_bridge_funcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) sii902x->bridge.of_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) sii902x->bridge.timings = &default_sii902x_timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) drm_bridge_add(&sii902x->bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) sii902x_audio_codec_init(sii902x, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) i2c_set_clientdata(sii902x->i2c, sii902x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) sii902x->i2cmux = i2c_mux_alloc(sii902x->i2c->adapter, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 1, 0, I2C_MUX_GATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) sii902x_i2c_bypass_select,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) sii902x_i2c_bypass_deselect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (!sii902x->i2cmux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) sii902x->i2cmux->priv = sii902x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) return i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) static int sii902x_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) struct device *dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) struct sii902x *sii902x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) ret = i2c_check_functionality(client->adapter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) I2C_FUNC_SMBUS_BYTE_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) dev_err(dev, "I2C adapter not suitable\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) sii902x = devm_kzalloc(dev, sizeof(*sii902x), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) if (!sii902x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) sii902x->i2c = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) sii902x->regmap = devm_regmap_init_i2c(client, &sii902x_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (IS_ERR(sii902x->regmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) return PTR_ERR(sii902x->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) sii902x->reset_gpio = devm_gpiod_get_optional(dev, "reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (IS_ERR(sii902x->reset_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) dev_err(dev, "Failed to retrieve/request reset gpio: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) PTR_ERR(sii902x->reset_gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) return PTR_ERR(sii902x->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) sii902x->enable_gpio = devm_gpiod_get_optional(dev, "enable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if (IS_ERR(sii902x->enable_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) dev_err(dev, "Failed to retrieve/request enable gpio: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) PTR_ERR(sii902x->enable_gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) return PTR_ERR(sii902x->enable_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) } else if (sii902x->enable_gpio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) gpiod_direction_output(sii902x->enable_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) usleep_range(1500, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) ret = of_property_read_u32(dev->of_node, "bus-format", &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) sii902x->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) case FORMAT_RGB_INPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) sii902x->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) case FORMAT_YCBCR422_INPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) sii902x->bus_format = MEDIA_BUS_FMT_YUYV8_1X16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) case FORMAT_YCBCR444_INPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) sii902x->bus_format = MEDIA_BUS_FMT_YUV8_1X24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) sii902x->bus_format = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) mutex_init(&sii902x->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) sii902x->supplies[0].supply = "iovcc";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) sii902x->supplies[1].supply = "cvcc12";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sii902x->supplies),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) sii902x->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) ret = regulator_bulk_enable(ARRAY_SIZE(sii902x->supplies),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) sii902x->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) dev_err_probe(dev, ret, "Failed to enable supplies");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) ret = sii902x_init(sii902x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) dev_err(dev, "Failed to init sii902x %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) sii902x->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) static int sii902x_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) struct sii902x *sii902x = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) i2c_mux_del_adapters(sii902x->i2cmux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) drm_bridge_remove(&sii902x->bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) sii902x->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) static const struct of_device_id sii902x_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) { .compatible = "sil,sii9022", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) MODULE_DEVICE_TABLE(of, sii902x_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) static const struct i2c_device_id sii902x_i2c_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) { "sii9022", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) MODULE_DEVICE_TABLE(i2c, sii902x_i2c_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) static struct i2c_driver sii902x_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) .probe = sii902x_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) .remove = sii902x_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) .name = "sii902x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) .of_match_table = sii902x_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) .id_table = sii902x_i2c_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) module_i2c_driver(sii902x_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) MODULE_DESCRIPTION("SII902x RGB -> HDMI bridges");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) MODULE_LICENSE("GPL");