1991 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Driver for Renesas R-Car MIPI CSI-2 Receiver4 *5 * Copyright (C) 2018 Renesas Electronics Corp.6 */7 8#include <linux/delay.h>9#include <linux/interrupt.h>10#include <linux/io.h>11#include <linux/module.h>12#include <linux/of.h>13#include <linux/of_graph.h>14#include <linux/platform_device.h>15#include <linux/pm_runtime.h>16#include <linux/reset.h>17#include <linux/sys_soc.h>18 19#include <media/mipi-csi2.h>20#include <media/v4l2-ctrls.h>21#include <media/v4l2-device.h>22#include <media/v4l2-fwnode.h>23#include <media/v4l2-mc.h>24#include <media/v4l2-subdev.h>25 26struct rcar_csi2;27 28/* Register offsets and bits */29 30/* Control Timing Select */31#define TREF_REG 0x0032#define TREF_TREF BIT(0)33 34/* Software Reset */35#define SRST_REG 0x0436#define SRST_SRST BIT(0)37 38/* PHY Operation Control */39#define PHYCNT_REG 0x0840#define PHYCNT_SHUTDOWNZ BIT(17)41#define PHYCNT_RSTZ BIT(16)42#define PHYCNT_ENABLECLK BIT(4)43#define PHYCNT_ENABLE_3 BIT(3)44#define PHYCNT_ENABLE_2 BIT(2)45#define PHYCNT_ENABLE_1 BIT(1)46#define PHYCNT_ENABLE_0 BIT(0)47 48/* Checksum Control */49#define CHKSUM_REG 0x0c50#define CHKSUM_ECC_EN BIT(1)51#define CHKSUM_CRC_EN BIT(0)52 53/*54 * Channel Data Type Select55 * VCDT[0-15]: Channel 0 VCDT[16-31]: Channel 156 * VCDT2[0-15]: Channel 2 VCDT2[16-31]: Channel 357 */58#define VCDT_REG 0x1059#define VCDT2_REG 0x1460#define VCDT_VCDTN_EN BIT(15)61#define VCDT_SEL_VC(n) (((n) & 0x3) << 8)62#define VCDT_SEL_DTN_ON BIT(6)63#define VCDT_SEL_DT(n) (((n) & 0x3f) << 0)64 65/* Frame Data Type Select */66#define FRDT_REG 0x1867 68/* Field Detection Control */69#define FLD_REG 0x1c70#define FLD_FLD_NUM(n) (((n) & 0xff) << 16)71#define FLD_DET_SEL(n) (((n) & 0x3) << 4)72#define FLD_FLD_EN4 BIT(3)73#define FLD_FLD_EN3 BIT(2)74#define FLD_FLD_EN2 BIT(1)75#define FLD_FLD_EN BIT(0)76 77/* Automatic Standby Control */78#define ASTBY_REG 0x2079 80/* Long Data Type Setting 0 */81#define LNGDT0_REG 0x2882 83/* Long Data Type Setting 1 */84#define LNGDT1_REG 0x2c85 86/* Interrupt Enable */87#define INTEN_REG 0x3088#define INTEN_INT_AFIFO_OF BIT(27)89#define INTEN_INT_ERRSOTHS BIT(4)90#define INTEN_INT_ERRSOTSYNCHS BIT(3)91 92/* Interrupt Source Mask */93#define INTCLOSE_REG 0x3494 95/* Interrupt Status Monitor */96#define INTSTATE_REG 0x3897#define INTSTATE_INT_ULPS_START BIT(7)98#define INTSTATE_INT_ULPS_END BIT(6)99 100/* Interrupt Error Status Monitor */101#define INTERRSTATE_REG 0x3c102 103/* Short Packet Data */104#define SHPDAT_REG 0x40105 106/* Short Packet Count */107#define SHPCNT_REG 0x44108 109/* LINK Operation Control */110#define LINKCNT_REG 0x48111#define LINKCNT_MONITOR_EN BIT(31)112#define LINKCNT_REG_MONI_PACT_EN BIT(25)113#define LINKCNT_ICLK_NONSTOP BIT(24)114 115/* Lane Swap */116#define LSWAP_REG 0x4c117#define LSWAP_L3SEL(n) (((n) & 0x3) << 6)118#define LSWAP_L2SEL(n) (((n) & 0x3) << 4)119#define LSWAP_L1SEL(n) (((n) & 0x3) << 2)120#define LSWAP_L0SEL(n) (((n) & 0x3) << 0)121 122/* PHY Test Interface Write Register */123#define PHTW_REG 0x50124#define PHTW_DWEN BIT(24)125#define PHTW_TESTDIN_DATA(n) (((n & 0xff)) << 16)126#define PHTW_CWEN BIT(8)127#define PHTW_TESTDIN_CODE(n) ((n & 0xff))128 129#define PHYFRX_REG 0x64130#define PHYFRX_FORCERX_MODE_3 BIT(3)131#define PHYFRX_FORCERX_MODE_2 BIT(2)132#define PHYFRX_FORCERX_MODE_1 BIT(1)133#define PHYFRX_FORCERX_MODE_0 BIT(0)134 135/* V4H BASE registers */136#define V4H_N_LANES_REG 0x0004137#define V4H_CSI2_RESETN_REG 0x0008138#define V4H_PHY_MODE_REG 0x001c139#define V4H_PHY_SHUTDOWNZ_REG 0x0040140#define V4H_DPHY_RSTZ_REG 0x0044141#define V4H_FLDC_REG 0x0804142#define V4H_FLDD_REG 0x0808143#define V4H_IDIC_REG 0x0810144#define V4H_PHY_EN_REG 0x2000145 146#define V4H_ST_PHYST_REG 0x2814147#define V4H_ST_PHYST_ST_PHY_READY BIT(31)148#define V4H_ST_PHYST_ST_STOPSTATE_3 BIT(3)149#define V4H_ST_PHYST_ST_STOPSTATE_2 BIT(2)150#define V4H_ST_PHYST_ST_STOPSTATE_1 BIT(1)151#define V4H_ST_PHYST_ST_STOPSTATE_0 BIT(0)152 153/* V4H PPI registers */154#define V4H_PPI_STARTUP_RW_COMMON_DPHY_REG(n) (0x21800 + ((n) * 2)) /* n = 0 - 9 */155#define V4H_PPI_STARTUP_RW_COMMON_STARTUP_1_1_REG 0x21822156#define V4H_PPI_CALIBCTRL_RW_COMMON_BG_0_REG 0x2184c157#define V4H_PPI_RW_LPDCOCAL_TIMEBASE_REG 0x21c02158#define V4H_PPI_RW_LPDCOCAL_NREF_REG 0x21c04159#define V4H_PPI_RW_LPDCOCAL_NREF_RANGE_REG 0x21c06160#define V4H_PPI_RW_LPDCOCAL_TWAIT_CONFIG_REG 0x21c0a161#define V4H_PPI_RW_LPDCOCAL_VT_CONFIG_REG 0x21c0c162#define V4H_PPI_RW_LPDCOCAL_COARSE_CFG_REG 0x21c10163#define V4H_PPI_RW_COMMON_CFG_REG 0x21c6c164#define V4H_PPI_RW_TERMCAL_CFG_0_REG 0x21c80165#define V4H_PPI_RW_OFFSETCAL_CFG_0_REG 0x21ca0166 167/* V4H CORE registers */168#define V4H_CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_REG(n) (0x22040 + ((n) * 2)) /* n = 0 - 15 */169#define V4H_CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_REG(n) (0x22440 + ((n) * 2)) /* n = 0 - 15 */170#define V4H_CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_REG(n) (0x22840 + ((n) * 2)) /* n = 0 - 15 */171#define V4H_CORE_DIG_IOCTRL_RW_AFE_LANE3_CTRL_2_REG(n) (0x22c40 + ((n) * 2)) /* n = 0 - 15 */172#define V4H_CORE_DIG_IOCTRL_RW_AFE_LANE4_CTRL_2_REG(n) (0x23040 + ((n) * 2)) /* n = 0 - 15 */173#define V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(n) (0x23840 + ((n) * 2)) /* n = 0 - 11 */174#define V4H_CORE_DIG_RW_COMMON_REG(n) (0x23880 + ((n) * 2)) /* n = 0 - 15 */175#define V4H_CORE_DIG_ANACTRL_RW_COMMON_ANACTRL_REG(n) (0x239e0 + ((n) * 2)) /* n = 0 - 3 */176#define V4H_CORE_DIG_CLANE_1_RW_CFG_0_REG 0x2a400177#define V4H_CORE_DIG_CLANE_1_RW_HS_TX_6_REG 0x2a60c178 179/* V4H C-PHY */180#define V4H_CORE_DIG_RW_TRIO0_REG(n) (0x22100 + ((n) * 2)) /* n = 0 - 3 */181#define V4H_CORE_DIG_RW_TRIO1_REG(n) (0x22500 + ((n) * 2)) /* n = 0 - 3 */182#define V4H_CORE_DIG_RW_TRIO2_REG(n) (0x22900 + ((n) * 2)) /* n = 0 - 3 */183#define V4H_CORE_DIG_CLANE_0_RW_LP_0_REG 0x2a080184#define V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(n) (0x2a100 + ((n) * 2)) /* n = 0 - 6 */185#define V4H_CORE_DIG_CLANE_1_RW_LP_0_REG 0x2a480186#define V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(n) (0x2a500 + ((n) * 2)) /* n = 0 - 6 */187#define V4H_CORE_DIG_CLANE_2_RW_LP_0_REG 0x2a880188#define V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(n) (0x2a900 + ((n) * 2)) /* n = 0 - 6 */189 190struct rcsi2_cphy_setting {191 u16 msps;192 u16 rx2;193 u16 trio0;194 u16 trio1;195 u16 trio2;196 u16 lane27;197 u16 lane29;198};199 200static const struct rcsi2_cphy_setting cphy_setting_table_r8a779g0[] = {201 { .msps = 80, .rx2 = 0x38, .trio0 = 0x024a, .trio1 = 0x0134, .trio2 = 0x6a, .lane27 = 0x0000, .lane29 = 0x0a24 },202 { .msps = 100, .rx2 = 0x38, .trio0 = 0x024a, .trio1 = 0x00f5, .trio2 = 0x55, .lane27 = 0x0000, .lane29 = 0x0a24 },203 { .msps = 200, .rx2 = 0x38, .trio0 = 0x024a, .trio1 = 0x0077, .trio2 = 0x2b, .lane27 = 0x0000, .lane29 = 0x0a44 },204 { .msps = 300, .rx2 = 0x38, .trio0 = 0x024a, .trio1 = 0x004d, .trio2 = 0x1d, .lane27 = 0x0000, .lane29 = 0x0a44 },205 { .msps = 400, .rx2 = 0x38, .trio0 = 0x024a, .trio1 = 0x0038, .trio2 = 0x16, .lane27 = 0x0000, .lane29 = 0x0a64 },206 { .msps = 500, .rx2 = 0x38, .trio0 = 0x024a, .trio1 = 0x002b, .trio2 = 0x12, .lane27 = 0x0000, .lane29 = 0x0a64 },207 { .msps = 600, .rx2 = 0x38, .trio0 = 0x024a, .trio1 = 0x0023, .trio2 = 0x0f, .lane27 = 0x0000, .lane29 = 0x0a64 },208 { .msps = 700, .rx2 = 0x38, .trio0 = 0x024a, .trio1 = 0x001d, .trio2 = 0x0d, .lane27 = 0x0000, .lane29 = 0x0a84 },209 { .msps = 800, .rx2 = 0x38, .trio0 = 0x024a, .trio1 = 0x0018, .trio2 = 0x0c, .lane27 = 0x0000, .lane29 = 0x0a84 },210 { .msps = 900, .rx2 = 0x38, .trio0 = 0x024a, .trio1 = 0x0015, .trio2 = 0x0b, .lane27 = 0x0000, .lane29 = 0x0a84 },211 { .msps = 1000, .rx2 = 0x3e, .trio0 = 0x024a, .trio1 = 0x0012, .trio2 = 0x0a, .lane27 = 0x0400, .lane29 = 0x0a84 },212 { .msps = 1100, .rx2 = 0x44, .trio0 = 0x024a, .trio1 = 0x000f, .trio2 = 0x09, .lane27 = 0x0800, .lane29 = 0x0a84 },213 { .msps = 1200, .rx2 = 0x4a, .trio0 = 0x024a, .trio1 = 0x000e, .trio2 = 0x08, .lane27 = 0x0c00, .lane29 = 0x0a84 },214 { .msps = 1300, .rx2 = 0x51, .trio0 = 0x024a, .trio1 = 0x000c, .trio2 = 0x08, .lane27 = 0x0c00, .lane29 = 0x0aa4 },215 { .msps = 1400, .rx2 = 0x57, .trio0 = 0x024a, .trio1 = 0x000b, .trio2 = 0x07, .lane27 = 0x1000, .lane29 = 0x0aa4 },216 { .msps = 1500, .rx2 = 0x5d, .trio0 = 0x044a, .trio1 = 0x0009, .trio2 = 0x07, .lane27 = 0x1000, .lane29 = 0x0aa4 },217 { .msps = 1600, .rx2 = 0x63, .trio0 = 0x044a, .trio1 = 0x0008, .trio2 = 0x07, .lane27 = 0x1400, .lane29 = 0x0aa4 },218 { .msps = 1700, .rx2 = 0x6a, .trio0 = 0x044a, .trio1 = 0x0007, .trio2 = 0x06, .lane27 = 0x1400, .lane29 = 0x0aa4 },219 { .msps = 1800, .rx2 = 0x70, .trio0 = 0x044a, .trio1 = 0x0007, .trio2 = 0x06, .lane27 = 0x1400, .lane29 = 0x0aa4 },220 { .msps = 1900, .rx2 = 0x76, .trio0 = 0x044a, .trio1 = 0x0006, .trio2 = 0x06, .lane27 = 0x1400, .lane29 = 0x0aa4 },221 { .msps = 2000, .rx2 = 0x7c, .trio0 = 0x044a, .trio1 = 0x0005, .trio2 = 0x06, .lane27 = 0x1800, .lane29 = 0x0aa4 },222 { .msps = 2100, .rx2 = 0x83, .trio0 = 0x044a, .trio1 = 0x0005, .trio2 = 0x05, .lane27 = 0x1800, .lane29 = 0x0aa4 },223 { .msps = 2200, .rx2 = 0x89, .trio0 = 0x064a, .trio1 = 0x0004, .trio2 = 0x05, .lane27 = 0x1800, .lane29 = 0x0aa4 },224 { .msps = 2300, .rx2 = 0x8f, .trio0 = 0x064a, .trio1 = 0x0003, .trio2 = 0x05, .lane27 = 0x1800, .lane29 = 0x0aa4 },225 { .msps = 2400, .rx2 = 0x95, .trio0 = 0x064a, .trio1 = 0x0003, .trio2 = 0x05, .lane27 = 0x1800, .lane29 = 0x0aa4 },226 { .msps = 2500, .rx2 = 0x9c, .trio0 = 0x064a, .trio1 = 0x0003, .trio2 = 0x05, .lane27 = 0x1c00, .lane29 = 0x0aa4 },227 { .msps = 2600, .rx2 = 0xa2, .trio0 = 0x064a, .trio1 = 0x0002, .trio2 = 0x05, .lane27 = 0x1c00, .lane29 = 0x0ad4 },228 { .msps = 2700, .rx2 = 0xa8, .trio0 = 0x064a, .trio1 = 0x0002, .trio2 = 0x05, .lane27 = 0x1c00, .lane29 = 0x0ad4 },229 { .msps = 2800, .rx2 = 0xae, .trio0 = 0x064a, .trio1 = 0x0002, .trio2 = 0x04, .lane27 = 0x1c00, .lane29 = 0x0ad4 },230 { .msps = 2900, .rx2 = 0xb5, .trio0 = 0x084a, .trio1 = 0x0001, .trio2 = 0x04, .lane27 = 0x1c00, .lane29 = 0x0ad4 },231 { .msps = 3000, .rx2 = 0xbb, .trio0 = 0x084a, .trio1 = 0x0001, .trio2 = 0x04, .lane27 = 0x1c00, .lane29 = 0x0ad4 },232 { .msps = 3100, .rx2 = 0xc1, .trio0 = 0x084a, .trio1 = 0x0001, .trio2 = 0x04, .lane27 = 0x1c00, .lane29 = 0x0ad4 },233 { .msps = 3200, .rx2 = 0xc7, .trio0 = 0x084a, .trio1 = 0x0001, .trio2 = 0x04, .lane27 = 0x1c00, .lane29 = 0x0ad4 },234 { .msps = 3300, .rx2 = 0xce, .trio0 = 0x084a, .trio1 = 0x0001, .trio2 = 0x04, .lane27 = 0x1c00, .lane29 = 0x0ad4 },235 { .msps = 3400, .rx2 = 0xd4, .trio0 = 0x084a, .trio1 = 0x0001, .trio2 = 0x04, .lane27 = 0x1c00, .lane29 = 0x0ad4 },236 { .msps = 3500, .rx2 = 0xda, .trio0 = 0x084a, .trio1 = 0x0001, .trio2 = 0x04, .lane27 = 0x1c00, .lane29 = 0x0ad4 },237 { /* sentinel */ },238};239 240struct phtw_value {241 u16 data;242 u16 code;243};244 245struct rcsi2_mbps_reg {246 u16 mbps;247 u16 reg;248};249 250static const struct rcsi2_mbps_reg phtw_mbps_v3u[] = {251 { .mbps = 1500, .reg = 0xcc },252 { .mbps = 1550, .reg = 0x1d },253 { .mbps = 1600, .reg = 0x27 },254 { .mbps = 1650, .reg = 0x30 },255 { .mbps = 1700, .reg = 0x39 },256 { .mbps = 1750, .reg = 0x42 },257 { .mbps = 1800, .reg = 0x4b },258 { .mbps = 1850, .reg = 0x55 },259 { .mbps = 1900, .reg = 0x5e },260 { .mbps = 1950, .reg = 0x67 },261 { .mbps = 2000, .reg = 0x71 },262 { .mbps = 2050, .reg = 0x79 },263 { .mbps = 2100, .reg = 0x83 },264 { .mbps = 2150, .reg = 0x8c },265 { .mbps = 2200, .reg = 0x95 },266 { .mbps = 2250, .reg = 0x9e },267 { .mbps = 2300, .reg = 0xa7 },268 { .mbps = 2350, .reg = 0xb0 },269 { .mbps = 2400, .reg = 0xba },270 { .mbps = 2450, .reg = 0xc3 },271 { .mbps = 2500, .reg = 0xcc },272 { /* sentinel */ },273};274 275static const struct rcsi2_mbps_reg phtw_mbps_h3_v3h_m3n[] = {276 { .mbps = 80, .reg = 0x86 },277 { .mbps = 90, .reg = 0x86 },278 { .mbps = 100, .reg = 0x87 },279 { .mbps = 110, .reg = 0x87 },280 { .mbps = 120, .reg = 0x88 },281 { .mbps = 130, .reg = 0x88 },282 { .mbps = 140, .reg = 0x89 },283 { .mbps = 150, .reg = 0x89 },284 { .mbps = 160, .reg = 0x8a },285 { .mbps = 170, .reg = 0x8a },286 { .mbps = 180, .reg = 0x8b },287 { .mbps = 190, .reg = 0x8b },288 { .mbps = 205, .reg = 0x8c },289 { .mbps = 220, .reg = 0x8d },290 { .mbps = 235, .reg = 0x8e },291 { .mbps = 250, .reg = 0x8e },292 { /* sentinel */ },293};294 295static const struct rcsi2_mbps_reg phtw_mbps_v3m_e3[] = {296 { .mbps = 80, .reg = 0x00 },297 { .mbps = 90, .reg = 0x20 },298 { .mbps = 100, .reg = 0x40 },299 { .mbps = 110, .reg = 0x02 },300 { .mbps = 130, .reg = 0x22 },301 { .mbps = 140, .reg = 0x42 },302 { .mbps = 150, .reg = 0x04 },303 { .mbps = 170, .reg = 0x24 },304 { .mbps = 180, .reg = 0x44 },305 { .mbps = 200, .reg = 0x06 },306 { .mbps = 220, .reg = 0x26 },307 { .mbps = 240, .reg = 0x46 },308 { .mbps = 250, .reg = 0x08 },309 { .mbps = 270, .reg = 0x28 },310 { .mbps = 300, .reg = 0x0a },311 { .mbps = 330, .reg = 0x2a },312 { .mbps = 360, .reg = 0x4a },313 { .mbps = 400, .reg = 0x0c },314 { .mbps = 450, .reg = 0x2c },315 { .mbps = 500, .reg = 0x0e },316 { .mbps = 550, .reg = 0x2e },317 { .mbps = 600, .reg = 0x10 },318 { .mbps = 650, .reg = 0x30 },319 { .mbps = 700, .reg = 0x12 },320 { .mbps = 750, .reg = 0x32 },321 { .mbps = 800, .reg = 0x52 },322 { .mbps = 850, .reg = 0x72 },323 { .mbps = 900, .reg = 0x14 },324 { .mbps = 950, .reg = 0x34 },325 { .mbps = 1000, .reg = 0x54 },326 { .mbps = 1050, .reg = 0x74 },327 { .mbps = 1125, .reg = 0x16 },328 { /* sentinel */ },329};330 331/* PHY Test Interface Clear */332#define PHTC_REG 0x58333#define PHTC_TESTCLR BIT(0)334 335/* PHY Frequency Control */336#define PHYPLL_REG 0x68337#define PHYPLL_HSFREQRANGE(n) ((n) << 16)338 339static const struct rcsi2_mbps_reg hsfreqrange_v3u[] = {340 { .mbps = 80, .reg = 0x00 },341 { .mbps = 90, .reg = 0x10 },342 { .mbps = 100, .reg = 0x20 },343 { .mbps = 110, .reg = 0x30 },344 { .mbps = 120, .reg = 0x01 },345 { .mbps = 130, .reg = 0x11 },346 { .mbps = 140, .reg = 0x21 },347 { .mbps = 150, .reg = 0x31 },348 { .mbps = 160, .reg = 0x02 },349 { .mbps = 170, .reg = 0x12 },350 { .mbps = 180, .reg = 0x22 },351 { .mbps = 190, .reg = 0x32 },352 { .mbps = 205, .reg = 0x03 },353 { .mbps = 220, .reg = 0x13 },354 { .mbps = 235, .reg = 0x23 },355 { .mbps = 250, .reg = 0x33 },356 { .mbps = 275, .reg = 0x04 },357 { .mbps = 300, .reg = 0x14 },358 { .mbps = 325, .reg = 0x25 },359 { .mbps = 350, .reg = 0x35 },360 { .mbps = 400, .reg = 0x05 },361 { .mbps = 450, .reg = 0x16 },362 { .mbps = 500, .reg = 0x26 },363 { .mbps = 550, .reg = 0x37 },364 { .mbps = 600, .reg = 0x07 },365 { .mbps = 650, .reg = 0x18 },366 { .mbps = 700, .reg = 0x28 },367 { .mbps = 750, .reg = 0x39 },368 { .mbps = 800, .reg = 0x09 },369 { .mbps = 850, .reg = 0x19 },370 { .mbps = 900, .reg = 0x29 },371 { .mbps = 950, .reg = 0x3a },372 { .mbps = 1000, .reg = 0x0a },373 { .mbps = 1050, .reg = 0x1a },374 { .mbps = 1100, .reg = 0x2a },375 { .mbps = 1150, .reg = 0x3b },376 { .mbps = 1200, .reg = 0x0b },377 { .mbps = 1250, .reg = 0x1b },378 { .mbps = 1300, .reg = 0x2b },379 { .mbps = 1350, .reg = 0x3c },380 { .mbps = 1400, .reg = 0x0c },381 { .mbps = 1450, .reg = 0x1c },382 { .mbps = 1500, .reg = 0x2c },383 { .mbps = 1550, .reg = 0x3d },384 { .mbps = 1600, .reg = 0x0d },385 { .mbps = 1650, .reg = 0x1d },386 { .mbps = 1700, .reg = 0x2e },387 { .mbps = 1750, .reg = 0x3e },388 { .mbps = 1800, .reg = 0x0e },389 { .mbps = 1850, .reg = 0x1e },390 { .mbps = 1900, .reg = 0x2f },391 { .mbps = 1950, .reg = 0x3f },392 { .mbps = 2000, .reg = 0x0f },393 { .mbps = 2050, .reg = 0x40 },394 { .mbps = 2100, .reg = 0x41 },395 { .mbps = 2150, .reg = 0x42 },396 { .mbps = 2200, .reg = 0x43 },397 { .mbps = 2300, .reg = 0x45 },398 { .mbps = 2350, .reg = 0x46 },399 { .mbps = 2400, .reg = 0x47 },400 { .mbps = 2450, .reg = 0x48 },401 { .mbps = 2500, .reg = 0x49 },402 { /* sentinel */ },403};404 405static const struct rcsi2_mbps_reg hsfreqrange_h3_v3h_m3n[] = {406 { .mbps = 80, .reg = 0x00 },407 { .mbps = 90, .reg = 0x10 },408 { .mbps = 100, .reg = 0x20 },409 { .mbps = 110, .reg = 0x30 },410 { .mbps = 120, .reg = 0x01 },411 { .mbps = 130, .reg = 0x11 },412 { .mbps = 140, .reg = 0x21 },413 { .mbps = 150, .reg = 0x31 },414 { .mbps = 160, .reg = 0x02 },415 { .mbps = 170, .reg = 0x12 },416 { .mbps = 180, .reg = 0x22 },417 { .mbps = 190, .reg = 0x32 },418 { .mbps = 205, .reg = 0x03 },419 { .mbps = 220, .reg = 0x13 },420 { .mbps = 235, .reg = 0x23 },421 { .mbps = 250, .reg = 0x33 },422 { .mbps = 275, .reg = 0x04 },423 { .mbps = 300, .reg = 0x14 },424 { .mbps = 325, .reg = 0x25 },425 { .mbps = 350, .reg = 0x35 },426 { .mbps = 400, .reg = 0x05 },427 { .mbps = 450, .reg = 0x16 },428 { .mbps = 500, .reg = 0x26 },429 { .mbps = 550, .reg = 0x37 },430 { .mbps = 600, .reg = 0x07 },431 { .mbps = 650, .reg = 0x18 },432 { .mbps = 700, .reg = 0x28 },433 { .mbps = 750, .reg = 0x39 },434 { .mbps = 800, .reg = 0x09 },435 { .mbps = 850, .reg = 0x19 },436 { .mbps = 900, .reg = 0x29 },437 { .mbps = 950, .reg = 0x3a },438 { .mbps = 1000, .reg = 0x0a },439 { .mbps = 1050, .reg = 0x1a },440 { .mbps = 1100, .reg = 0x2a },441 { .mbps = 1150, .reg = 0x3b },442 { .mbps = 1200, .reg = 0x0b },443 { .mbps = 1250, .reg = 0x1b },444 { .mbps = 1300, .reg = 0x2b },445 { .mbps = 1350, .reg = 0x3c },446 { .mbps = 1400, .reg = 0x0c },447 { .mbps = 1450, .reg = 0x1c },448 { .mbps = 1500, .reg = 0x2c },449 { /* sentinel */ },450};451 452static const struct rcsi2_mbps_reg hsfreqrange_m3w[] = {453 { .mbps = 80, .reg = 0x00 },454 { .mbps = 90, .reg = 0x10 },455 { .mbps = 100, .reg = 0x20 },456 { .mbps = 110, .reg = 0x30 },457 { .mbps = 120, .reg = 0x01 },458 { .mbps = 130, .reg = 0x11 },459 { .mbps = 140, .reg = 0x21 },460 { .mbps = 150, .reg = 0x31 },461 { .mbps = 160, .reg = 0x02 },462 { .mbps = 170, .reg = 0x12 },463 { .mbps = 180, .reg = 0x22 },464 { .mbps = 190, .reg = 0x32 },465 { .mbps = 205, .reg = 0x03 },466 { .mbps = 220, .reg = 0x13 },467 { .mbps = 235, .reg = 0x23 },468 { .mbps = 250, .reg = 0x33 },469 { .mbps = 275, .reg = 0x04 },470 { .mbps = 300, .reg = 0x14 },471 { .mbps = 325, .reg = 0x05 },472 { .mbps = 350, .reg = 0x15 },473 { .mbps = 400, .reg = 0x25 },474 { .mbps = 450, .reg = 0x06 },475 { .mbps = 500, .reg = 0x16 },476 { .mbps = 550, .reg = 0x07 },477 { .mbps = 600, .reg = 0x17 },478 { .mbps = 650, .reg = 0x08 },479 { .mbps = 700, .reg = 0x18 },480 { .mbps = 750, .reg = 0x09 },481 { .mbps = 800, .reg = 0x19 },482 { .mbps = 850, .reg = 0x29 },483 { .mbps = 900, .reg = 0x39 },484 { .mbps = 950, .reg = 0x0a },485 { .mbps = 1000, .reg = 0x1a },486 { .mbps = 1050, .reg = 0x2a },487 { .mbps = 1100, .reg = 0x3a },488 { .mbps = 1150, .reg = 0x0b },489 { .mbps = 1200, .reg = 0x1b },490 { .mbps = 1250, .reg = 0x2b },491 { .mbps = 1300, .reg = 0x3b },492 { .mbps = 1350, .reg = 0x0c },493 { .mbps = 1400, .reg = 0x1c },494 { .mbps = 1450, .reg = 0x2c },495 { .mbps = 1500, .reg = 0x3c },496 { /* sentinel */ },497};498 499/* PHY ESC Error Monitor */500#define PHEERM_REG 0x74501 502/* PHY Clock Lane Monitor */503#define PHCLM_REG 0x78504#define PHCLM_STOPSTATECKL BIT(0)505 506/* PHY Data Lane Monitor */507#define PHDLM_REG 0x7c508 509/* CSI0CLK Frequency Configuration Preset Register */510#define CSI0CLKFCPR_REG 0x260511#define CSI0CLKFREQRANGE(n) ((n & 0x3f) << 16)512 513struct rcar_csi2_format {514 u32 code;515 unsigned int datatype;516 unsigned int bpp;517};518 519static const struct rcar_csi2_format rcar_csi2_formats[] = {520 {521 .code = MEDIA_BUS_FMT_RGB888_1X24,522 .datatype = MIPI_CSI2_DT_RGB888,523 .bpp = 24,524 }, {525 .code = MEDIA_BUS_FMT_UYVY8_1X16,526 .datatype = MIPI_CSI2_DT_YUV422_8B,527 .bpp = 16,528 }, {529 .code = MEDIA_BUS_FMT_YUYV8_1X16,530 .datatype = MIPI_CSI2_DT_YUV422_8B,531 .bpp = 16,532 }, {533 .code = MEDIA_BUS_FMT_UYVY8_2X8,534 .datatype = MIPI_CSI2_DT_YUV422_8B,535 .bpp = 16,536 }, {537 .code = MEDIA_BUS_FMT_YUYV10_2X10,538 .datatype = MIPI_CSI2_DT_YUV422_8B,539 .bpp = 20,540 }, {541 .code = MEDIA_BUS_FMT_Y10_1X10,542 .datatype = MIPI_CSI2_DT_RAW10,543 .bpp = 10,544 }, {545 .code = MEDIA_BUS_FMT_SBGGR8_1X8,546 .datatype = MIPI_CSI2_DT_RAW8,547 .bpp = 8,548 }, {549 .code = MEDIA_BUS_FMT_SGBRG8_1X8,550 .datatype = MIPI_CSI2_DT_RAW8,551 .bpp = 8,552 }, {553 .code = MEDIA_BUS_FMT_SGRBG8_1X8,554 .datatype = MIPI_CSI2_DT_RAW8,555 .bpp = 8,556 }, {557 .code = MEDIA_BUS_FMT_SRGGB8_1X8,558 .datatype = MIPI_CSI2_DT_RAW8,559 .bpp = 8,560 }, {561 .code = MEDIA_BUS_FMT_Y8_1X8,562 .datatype = MIPI_CSI2_DT_RAW8,563 .bpp = 8,564 },565};566 567static const struct rcar_csi2_format *rcsi2_code_to_fmt(unsigned int code)568{569 unsigned int i;570 571 for (i = 0; i < ARRAY_SIZE(rcar_csi2_formats); i++)572 if (rcar_csi2_formats[i].code == code)573 return &rcar_csi2_formats[i];574 575 return NULL;576}577 578enum rcar_csi2_pads {579 RCAR_CSI2_SINK,580 RCAR_CSI2_SOURCE_VC0,581 RCAR_CSI2_SOURCE_VC1,582 RCAR_CSI2_SOURCE_VC2,583 RCAR_CSI2_SOURCE_VC3,584 NR_OF_RCAR_CSI2_PAD,585};586 587struct rcar_csi2_info {588 int (*init_phtw)(struct rcar_csi2 *priv, unsigned int mbps);589 int (*phy_post_init)(struct rcar_csi2 *priv);590 int (*start_receiver)(struct rcar_csi2 *priv,591 struct v4l2_subdev_state *state);592 void (*enter_standby)(struct rcar_csi2 *priv);593 const struct rcsi2_mbps_reg *hsfreqrange;594 unsigned int csi0clkfreqrange;595 unsigned int num_channels;596 bool clear_ulps;597 bool use_isp;598 bool support_dphy;599 bool support_cphy;600};601 602struct rcar_csi2 {603 struct device *dev;604 void __iomem *base;605 const struct rcar_csi2_info *info;606 struct reset_control *rstc;607 608 struct v4l2_subdev subdev;609 struct media_pad pads[NR_OF_RCAR_CSI2_PAD];610 611 struct v4l2_async_notifier notifier;612 struct v4l2_subdev *remote;613 unsigned int remote_pad;614 615 int channel_vc[4];616 617 int stream_count;618 619 bool cphy;620 unsigned short lanes;621 unsigned char lane_swap[4];622};623 624static inline struct rcar_csi2 *sd_to_csi2(struct v4l2_subdev *sd)625{626 return container_of(sd, struct rcar_csi2, subdev);627}628 629static inline struct rcar_csi2 *notifier_to_csi2(struct v4l2_async_notifier *n)630{631 return container_of(n, struct rcar_csi2, notifier);632}633 634static unsigned int rcsi2_num_pads(const struct rcar_csi2 *priv)635{636 /* Used together with R-Car ISP: one sink and one source pad. */637 if (priv->info->use_isp)638 return 2;639 640 /* Used together with R-Car VIN: one sink and four source pads. */641 return 5;642}643 644static u32 rcsi2_read(struct rcar_csi2 *priv, unsigned int reg)645{646 return ioread32(priv->base + reg);647}648 649static void rcsi2_write(struct rcar_csi2 *priv, unsigned int reg, u32 data)650{651 iowrite32(data, priv->base + reg);652}653 654static void rcsi2_write16(struct rcar_csi2 *priv, unsigned int reg, u16 data)655{656 iowrite16(data, priv->base + reg);657}658 659static void rcsi2_enter_standby_gen3(struct rcar_csi2 *priv)660{661 rcsi2_write(priv, PHYCNT_REG, 0);662 rcsi2_write(priv, PHTC_REG, PHTC_TESTCLR);663}664 665static void rcsi2_enter_standby(struct rcar_csi2 *priv)666{667 if (priv->info->enter_standby)668 priv->info->enter_standby(priv);669 670 reset_control_assert(priv->rstc);671 usleep_range(100, 150);672 pm_runtime_put(priv->dev);673}674 675static int rcsi2_exit_standby(struct rcar_csi2 *priv)676{677 int ret;678 679 ret = pm_runtime_resume_and_get(priv->dev);680 if (ret < 0)681 return ret;682 683 reset_control_deassert(priv->rstc);684 685 return 0;686}687 688static int rcsi2_wait_phy_start(struct rcar_csi2 *priv,689 unsigned int lanes)690{691 unsigned int timeout;692 693 /* Wait for the clock and data lanes to enter LP-11 state. */694 for (timeout = 0; timeout <= 20; timeout++) {695 const u32 lane_mask = (1 << lanes) - 1;696 697 if ((rcsi2_read(priv, PHCLM_REG) & PHCLM_STOPSTATECKL) &&698 (rcsi2_read(priv, PHDLM_REG) & lane_mask) == lane_mask)699 return 0;700 701 usleep_range(1000, 2000);702 }703 704 dev_err(priv->dev, "Timeout waiting for LP-11 state\n");705 706 return -ETIMEDOUT;707}708 709static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps)710{711 const struct rcsi2_mbps_reg *hsfreq;712 const struct rcsi2_mbps_reg *hsfreq_prev = NULL;713 714 if (mbps < priv->info->hsfreqrange->mbps)715 dev_warn(priv->dev, "%u Mbps less than min PHY speed %u Mbps",716 mbps, priv->info->hsfreqrange->mbps);717 718 for (hsfreq = priv->info->hsfreqrange; hsfreq->mbps != 0; hsfreq++) {719 if (hsfreq->mbps >= mbps)720 break;721 hsfreq_prev = hsfreq;722 }723 724 if (!hsfreq->mbps) {725 dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps);726 return -ERANGE;727 }728 729 if (hsfreq_prev &&730 ((mbps - hsfreq_prev->mbps) <= (hsfreq->mbps - mbps)))731 hsfreq = hsfreq_prev;732 733 rcsi2_write(priv, PHYPLL_REG, PHYPLL_HSFREQRANGE(hsfreq->reg));734 735 return 0;736}737 738static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp,739 unsigned int lanes)740{741 struct v4l2_subdev *source;742 struct v4l2_ctrl *ctrl;743 u64 mbps;744 745 if (!priv->remote)746 return -ENODEV;747 748 source = priv->remote;749 750 /* Read the pixel rate control from remote. */751 ctrl = v4l2_ctrl_find(source->ctrl_handler, V4L2_CID_PIXEL_RATE);752 if (!ctrl) {753 dev_err(priv->dev, "no pixel rate control in subdev %s\n",754 source->name);755 return -EINVAL;756 }757 758 /*759 * Calculate the phypll in mbps.760 * link_freq = (pixel_rate * bits_per_sample) / (2 * nr_of_lanes)761 * bps = link_freq * 2762 */763 mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp;764 do_div(mbps, lanes * 1000000);765 766 /* Adjust for C-PHY, divide by 2.8. */767 if (priv->cphy)768 mbps = div_u64(mbps * 5, 14);769 770 return mbps;771}772 773static int rcsi2_get_active_lanes(struct rcar_csi2 *priv,774 unsigned int *lanes)775{776 struct v4l2_mbus_config mbus_config = { 0 };777 int ret;778 779 *lanes = priv->lanes;780 781 ret = v4l2_subdev_call(priv->remote, pad, get_mbus_config,782 priv->remote_pad, &mbus_config);783 if (ret == -ENOIOCTLCMD) {784 dev_dbg(priv->dev, "No remote mbus configuration available\n");785 return 0;786 }787 788 if (ret) {789 dev_err(priv->dev, "Failed to get remote mbus configuration\n");790 return ret;791 }792 793 switch (mbus_config.type) {794 case V4L2_MBUS_CSI2_CPHY:795 if (!priv->cphy)796 return -EINVAL;797 break;798 case V4L2_MBUS_CSI2_DPHY:799 if (priv->cphy)800 return -EINVAL;801 break;802 default:803 dev_err(priv->dev, "Unsupported media bus type %u\n",804 mbus_config.type);805 return -EINVAL;806 }807 808 if (mbus_config.bus.mipi_csi2.num_data_lanes > priv->lanes) {809 dev_err(priv->dev,810 "Unsupported mbus config: too many data lanes %u\n",811 mbus_config.bus.mipi_csi2.num_data_lanes);812 return -EINVAL;813 }814 815 *lanes = mbus_config.bus.mipi_csi2.num_data_lanes;816 817 return 0;818}819 820static int rcsi2_start_receiver_gen3(struct rcar_csi2 *priv,821 struct v4l2_subdev_state *state)822{823 const struct rcar_csi2_format *format;824 u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0;825 const struct v4l2_mbus_framefmt *fmt;826 unsigned int lanes;827 unsigned int i;828 int mbps, ret;829 830 /* Use the format on the sink pad to compute the receiver config. */831 fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);832 833 dev_dbg(priv->dev, "Input size (%ux%u%c)\n",834 fmt->width, fmt->height,835 fmt->field == V4L2_FIELD_NONE ? 'p' : 'i');836 837 /* Code is validated in set_fmt. */838 format = rcsi2_code_to_fmt(fmt->code);839 if (!format)840 return -EINVAL;841 842 /*843 * Enable all supported CSI-2 channels with virtual channel and844 * data type matching.845 *846 * NOTE: It's not possible to get individual datatype for each847 * source virtual channel. Once this is possible in V4L2848 * it should be used here.849 */850 for (i = 0; i < priv->info->num_channels; i++) {851 u32 vcdt_part;852 853 if (priv->channel_vc[i] < 0)854 continue;855 856 vcdt_part = VCDT_SEL_VC(priv->channel_vc[i]) | VCDT_VCDTN_EN |857 VCDT_SEL_DTN_ON | VCDT_SEL_DT(format->datatype);858 859 /* Store in correct reg and offset. */860 if (i < 2)861 vcdt |= vcdt_part << ((i % 2) * 16);862 else863 vcdt2 |= vcdt_part << ((i % 2) * 16);864 }865 866 if (fmt->field == V4L2_FIELD_ALTERNATE) {867 fld = FLD_DET_SEL(1) | FLD_FLD_EN4 | FLD_FLD_EN3 | FLD_FLD_EN2868 | FLD_FLD_EN;869 870 if (fmt->height == 240)871 fld |= FLD_FLD_NUM(0);872 else873 fld |= FLD_FLD_NUM(1);874 }875 876 /*877 * Get the number of active data lanes inspecting the remote mbus878 * configuration.879 */880 ret = rcsi2_get_active_lanes(priv, &lanes);881 if (ret)882 return ret;883 884 phycnt = PHYCNT_ENABLECLK;885 phycnt |= (1 << lanes) - 1;886 887 mbps = rcsi2_calc_mbps(priv, format->bpp, lanes);888 if (mbps < 0)889 return mbps;890 891 /* Enable interrupts. */892 rcsi2_write(priv, INTEN_REG, INTEN_INT_AFIFO_OF | INTEN_INT_ERRSOTHS893 | INTEN_INT_ERRSOTSYNCHS);894 895 /* Init */896 rcsi2_write(priv, TREF_REG, TREF_TREF);897 rcsi2_write(priv, PHTC_REG, 0);898 899 /* Configure */900 if (!priv->info->use_isp) {901 rcsi2_write(priv, VCDT_REG, vcdt);902 if (vcdt2)903 rcsi2_write(priv, VCDT2_REG, vcdt2);904 }905 906 /* Lanes are zero indexed. */907 rcsi2_write(priv, LSWAP_REG,908 LSWAP_L0SEL(priv->lane_swap[0] - 1) |909 LSWAP_L1SEL(priv->lane_swap[1] - 1) |910 LSWAP_L2SEL(priv->lane_swap[2] - 1) |911 LSWAP_L3SEL(priv->lane_swap[3] - 1));912 913 /* Start */914 if (priv->info->init_phtw) {915 ret = priv->info->init_phtw(priv, mbps);916 if (ret)917 return ret;918 }919 920 if (priv->info->hsfreqrange) {921 ret = rcsi2_set_phypll(priv, mbps);922 if (ret)923 return ret;924 }925 926 if (priv->info->csi0clkfreqrange)927 rcsi2_write(priv, CSI0CLKFCPR_REG,928 CSI0CLKFREQRANGE(priv->info->csi0clkfreqrange));929 930 if (priv->info->use_isp)931 rcsi2_write(priv, PHYFRX_REG,932 PHYFRX_FORCERX_MODE_3 | PHYFRX_FORCERX_MODE_2 |933 PHYFRX_FORCERX_MODE_1 | PHYFRX_FORCERX_MODE_0);934 935 rcsi2_write(priv, PHYCNT_REG, phycnt);936 rcsi2_write(priv, LINKCNT_REG, LINKCNT_MONITOR_EN |937 LINKCNT_REG_MONI_PACT_EN | LINKCNT_ICLK_NONSTOP);938 rcsi2_write(priv, FLD_REG, fld);939 rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ);940 rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ | PHYCNT_RSTZ);941 942 ret = rcsi2_wait_phy_start(priv, lanes);943 if (ret)944 return ret;945 946 if (priv->info->use_isp)947 rcsi2_write(priv, PHYFRX_REG, 0);948 949 /* Run post PHY start initialization, if needed. */950 if (priv->info->phy_post_init) {951 ret = priv->info->phy_post_init(priv);952 if (ret)953 return ret;954 }955 956 /* Clear Ultra Low Power interrupt. */957 if (priv->info->clear_ulps)958 rcsi2_write(priv, INTSTATE_REG,959 INTSTATE_INT_ULPS_START |960 INTSTATE_INT_ULPS_END);961 return 0;962}963 964static int rcsi2_wait_phy_start_v4h(struct rcar_csi2 *priv, u32 match)965{966 unsigned int timeout;967 u32 status;968 969 for (timeout = 0; timeout <= 10; timeout++) {970 status = rcsi2_read(priv, V4H_ST_PHYST_REG);971 if ((status & match) == match)972 return 0;973 974 usleep_range(1000, 2000);975 }976 977 return -ETIMEDOUT;978}979 980static int rcsi2_c_phy_setting_v4h(struct rcar_csi2 *priv, int msps)981{982 const struct rcsi2_cphy_setting *conf;983 984 for (conf = cphy_setting_table_r8a779g0; conf->msps != 0; conf++) {985 if (conf->msps > msps)986 break;987 }988 989 if (!conf->msps) {990 dev_err(priv->dev, "Unsupported PHY speed for msps setting (%u Msps)", msps);991 return -ERANGE;992 }993 994 /* C-PHY specific */995 rcsi2_write16(priv, V4H_CORE_DIG_RW_COMMON_REG(7), 0x0155);996 rcsi2_write16(priv, V4H_PPI_STARTUP_RW_COMMON_DPHY_REG(7), 0x0068);997 rcsi2_write16(priv, V4H_PPI_STARTUP_RW_COMMON_DPHY_REG(8), 0x0010);998 999 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_LP_0_REG, 0x463c);1000 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_LP_0_REG, 0x463c);1001 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_LP_0_REG, 0x463c);1002 1003 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(0), 0x00d5);1004 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(0), 0x00d5);1005 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(0), 0x00d5);1006 1007 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(1), 0x0013);1008 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(1), 0x0013);1009 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(1), 0x0013);1010 1011 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(5), 0x0013);1012 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(5), 0x0013);1013 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(5), 0x0013);1014 1015 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(6), 0x000a);1016 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(6), 0x000a);1017 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(6), 0x000a);1018 1019 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(2), conf->rx2);1020 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(2), conf->rx2);1021 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(2), conf->rx2);1022 1023 rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_REG(2), 0x0001);1024 rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_REG(2), 0);1025 rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_REG(2), 0x0001);1026 rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE3_CTRL_2_REG(2), 0x0001);1027 rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE4_CTRL_2_REG(2), 0);1028 1029 rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO0_REG(0), conf->trio0);1030 rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO1_REG(0), conf->trio0);1031 rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO2_REG(0), conf->trio0);1032 1033 rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO0_REG(2), conf->trio2);1034 rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO1_REG(2), conf->trio2);1035 rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO2_REG(2), conf->trio2);1036 1037 rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO0_REG(1), conf->trio1);1038 rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO1_REG(1), conf->trio1);1039 rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO2_REG(1), conf->trio1);1040 1041 /*1042 * Configure pin-swap.1043 * TODO: This registers is not documented yet, the values should depend1044 * on the 'clock-lanes' and 'data-lanes' devicetree properties.1045 */1046 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_CFG_0_REG, 0xf5);1047 rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_TX_6_REG, 0x5000);1048 1049 /* Leave Shutdown mode */1050 rcsi2_write(priv, V4H_DPHY_RSTZ_REG, BIT(0));1051 rcsi2_write(priv, V4H_PHY_SHUTDOWNZ_REG, BIT(0));1052 1053 /* Wait for calibration */1054 if (rcsi2_wait_phy_start_v4h(priv, V4H_ST_PHYST_ST_PHY_READY)) {1055 dev_err(priv->dev, "PHY calibration failed\n");1056 return -ETIMEDOUT;1057 }1058 1059 /* C-PHY setting - analog programing*/1060 rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_REG(9), conf->lane29);1061 rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_REG(7), conf->lane27);1062 1063 return 0;1064}1065 1066static int rcsi2_start_receiver_v4h(struct rcar_csi2 *priv,1067 struct v4l2_subdev_state *state)1068{1069 const struct rcar_csi2_format *format;1070 const struct v4l2_mbus_framefmt *fmt;1071 unsigned int lanes;1072 int msps;1073 int ret;1074 1075 /* Use the format on the sink pad to compute the receiver config. */1076 fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);1077 format = rcsi2_code_to_fmt(fmt->code);1078 if (!format)1079 return -EINVAL;1080 1081 ret = rcsi2_get_active_lanes(priv, &lanes);1082 if (ret)1083 return ret;1084 1085 msps = rcsi2_calc_mbps(priv, format->bpp, lanes);1086 if (msps < 0)1087 return msps;1088 1089 /* Reset LINK and PHY*/1090 rcsi2_write(priv, V4H_CSI2_RESETN_REG, 0);1091 rcsi2_write(priv, V4H_DPHY_RSTZ_REG, 0);1092 rcsi2_write(priv, V4H_PHY_SHUTDOWNZ_REG, 0);1093 1094 /* PHY static setting */1095 rcsi2_write(priv, V4H_PHY_EN_REG, BIT(0));1096 rcsi2_write(priv, V4H_FLDC_REG, 0);1097 rcsi2_write(priv, V4H_FLDD_REG, 0);1098 rcsi2_write(priv, V4H_IDIC_REG, 0);1099 rcsi2_write(priv, V4H_PHY_MODE_REG, BIT(0));1100 rcsi2_write(priv, V4H_N_LANES_REG, lanes - 1);1101 1102 /* Reset CSI2 */1103 rcsi2_write(priv, V4H_CSI2_RESETN_REG, BIT(0));1104 1105 /* Registers static setting through APB */1106 /* Common setting */1107 rcsi2_write16(priv, V4H_CORE_DIG_ANACTRL_RW_COMMON_ANACTRL_REG(0), 0x1bfd);1108 rcsi2_write16(priv, V4H_PPI_STARTUP_RW_COMMON_STARTUP_1_1_REG, 0x0233);1109 rcsi2_write16(priv, V4H_PPI_STARTUP_RW_COMMON_DPHY_REG(6), 0x0027);1110 rcsi2_write16(priv, V4H_PPI_CALIBCTRL_RW_COMMON_BG_0_REG, 0x01f4);1111 rcsi2_write16(priv, V4H_PPI_RW_TERMCAL_CFG_0_REG, 0x0013);1112 rcsi2_write16(priv, V4H_PPI_RW_OFFSETCAL_CFG_0_REG, 0x0003);1113 rcsi2_write16(priv, V4H_PPI_RW_LPDCOCAL_TIMEBASE_REG, 0x004f);1114 rcsi2_write16(priv, V4H_PPI_RW_LPDCOCAL_NREF_REG, 0x0320);1115 rcsi2_write16(priv, V4H_PPI_RW_LPDCOCAL_NREF_RANGE_REG, 0x000f);1116 rcsi2_write16(priv, V4H_PPI_RW_LPDCOCAL_TWAIT_CONFIG_REG, 0xfe18);1117 rcsi2_write16(priv, V4H_PPI_RW_LPDCOCAL_VT_CONFIG_REG, 0x0c3c);1118 rcsi2_write16(priv, V4H_PPI_RW_LPDCOCAL_COARSE_CFG_REG, 0x0105);1119 rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(6), 0x1000);1120 rcsi2_write16(priv, V4H_PPI_RW_COMMON_CFG_REG, 0x0003);1121 1122 /* C-PHY settings */1123 ret = rcsi2_c_phy_setting_v4h(priv, msps);1124 if (ret)1125 return ret;1126 1127 rcsi2_wait_phy_start_v4h(priv, V4H_ST_PHYST_ST_STOPSTATE_0 |1128 V4H_ST_PHYST_ST_STOPSTATE_1 |1129 V4H_ST_PHYST_ST_STOPSTATE_2);1130 1131 return 0;1132}1133 1134static int rcsi2_start(struct rcar_csi2 *priv, struct v4l2_subdev_state *state)1135{1136 int ret;1137 1138 ret = rcsi2_exit_standby(priv);1139 if (ret < 0)1140 return ret;1141 1142 ret = priv->info->start_receiver(priv, state);1143 if (ret) {1144 rcsi2_enter_standby(priv);1145 return ret;1146 }1147 1148 ret = v4l2_subdev_call(priv->remote, video, s_stream, 1);1149 if (ret) {1150 rcsi2_enter_standby(priv);1151 return ret;1152 }1153 1154 return 0;1155}1156 1157static void rcsi2_stop(struct rcar_csi2 *priv)1158{1159 rcsi2_enter_standby(priv);1160 v4l2_subdev_call(priv->remote, video, s_stream, 0);1161}1162 1163static int rcsi2_s_stream(struct v4l2_subdev *sd, int enable)1164{1165 struct rcar_csi2 *priv = sd_to_csi2(sd);1166 struct v4l2_subdev_state *state;1167 int ret = 0;1168 1169 if (!priv->remote)1170 return -ENODEV;1171 1172 state = v4l2_subdev_lock_and_get_active_state(&priv->subdev);1173 1174 if (enable && priv->stream_count == 0) {1175 ret = rcsi2_start(priv, state);1176 if (ret)1177 goto out;1178 } else if (!enable && priv->stream_count == 1) {1179 rcsi2_stop(priv);1180 }1181 1182 priv->stream_count += enable ? 1 : -1;1183out:1184 v4l2_subdev_unlock_state(state);1185 1186 return ret;1187}1188 1189static int rcsi2_set_pad_format(struct v4l2_subdev *sd,1190 struct v4l2_subdev_state *state,1191 struct v4l2_subdev_format *format)1192{1193 struct rcar_csi2 *priv = sd_to_csi2(sd);1194 unsigned int num_pads = rcsi2_num_pads(priv);1195 1196 if (format->pad > RCAR_CSI2_SINK)1197 return v4l2_subdev_get_fmt(sd, state, format);1198 1199 if (!rcsi2_code_to_fmt(format->format.code))1200 format->format.code = rcar_csi2_formats[0].code;1201 1202 *v4l2_subdev_state_get_format(state, format->pad) = format->format;1203 1204 /* Propagate the format to the source pads. */1205 for (unsigned int i = RCAR_CSI2_SOURCE_VC0; i < num_pads; i++)1206 *v4l2_subdev_state_get_format(state, i) = format->format;1207 1208 return 0;1209}1210 1211static const struct v4l2_subdev_video_ops rcar_csi2_video_ops = {1212 .s_stream = rcsi2_s_stream,1213};1214 1215static const struct v4l2_subdev_pad_ops rcar_csi2_pad_ops = {1216 .set_fmt = rcsi2_set_pad_format,1217 .get_fmt = v4l2_subdev_get_fmt,1218};1219 1220static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {1221 .video = &rcar_csi2_video_ops,1222 .pad = &rcar_csi2_pad_ops,1223};1224 1225static int rcsi2_init_state(struct v4l2_subdev *sd,1226 struct v4l2_subdev_state *state)1227{1228 struct rcar_csi2 *priv = sd_to_csi2(sd);1229 unsigned int num_pads = rcsi2_num_pads(priv);1230 1231 static const struct v4l2_mbus_framefmt rcar_csi2_default_fmt = {1232 .width = 1920,1233 .height = 1080,1234 .code = MEDIA_BUS_FMT_RGB888_1X24,1235 .colorspace = V4L2_COLORSPACE_SRGB,1236 .field = V4L2_FIELD_NONE,1237 .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT,1238 .quantization = V4L2_QUANTIZATION_DEFAULT,1239 .xfer_func = V4L2_XFER_FUNC_DEFAULT,1240 };1241 1242 for (unsigned int i = RCAR_CSI2_SINK; i < num_pads; i++)1243 *v4l2_subdev_state_get_format(state, i) = rcar_csi2_default_fmt;1244 1245 return 0;1246}1247 1248static const struct v4l2_subdev_internal_ops rcar_csi2_internal_ops = {1249 .init_state = rcsi2_init_state,1250};1251 1252static irqreturn_t rcsi2_irq(int irq, void *data)1253{1254 struct rcar_csi2 *priv = data;1255 u32 status, err_status;1256 1257 status = rcsi2_read(priv, INTSTATE_REG);1258 err_status = rcsi2_read(priv, INTERRSTATE_REG);1259 1260 if (!status)1261 return IRQ_HANDLED;1262 1263 rcsi2_write(priv, INTSTATE_REG, status);1264 1265 if (!err_status)1266 return IRQ_HANDLED;1267 1268 rcsi2_write(priv, INTERRSTATE_REG, err_status);1269 1270 dev_info(priv->dev, "Transfer error, restarting CSI-2 receiver\n");1271 1272 return IRQ_WAKE_THREAD;1273}1274 1275static irqreturn_t rcsi2_irq_thread(int irq, void *data)1276{1277 struct v4l2_subdev_state *state;1278 struct rcar_csi2 *priv = data;1279 1280 state = v4l2_subdev_lock_and_get_active_state(&priv->subdev);1281 1282 rcsi2_stop(priv);1283 usleep_range(1000, 2000);1284 if (rcsi2_start(priv, state))1285 dev_warn(priv->dev, "Failed to restart CSI-2 receiver\n");1286 1287 v4l2_subdev_unlock_state(state);1288 1289 return IRQ_HANDLED;1290}1291 1292/* -----------------------------------------------------------------------------1293 * Async handling and registration of subdevices and links.1294 */1295 1296static int rcsi2_notify_bound(struct v4l2_async_notifier *notifier,1297 struct v4l2_subdev *subdev,1298 struct v4l2_async_connection *asc)1299{1300 struct rcar_csi2 *priv = notifier_to_csi2(notifier);1301 int pad;1302 1303 pad = media_entity_get_fwnode_pad(&subdev->entity, asc->match.fwnode,1304 MEDIA_PAD_FL_SOURCE);1305 if (pad < 0) {1306 dev_err(priv->dev, "Failed to find pad for %s\n", subdev->name);1307 return pad;1308 }1309 1310 priv->remote = subdev;1311 priv->remote_pad = pad;1312 1313 dev_dbg(priv->dev, "Bound %s pad: %d\n", subdev->name, pad);1314 1315 return media_create_pad_link(&subdev->entity, pad,1316 &priv->subdev.entity, 0,1317 MEDIA_LNK_FL_ENABLED |1318 MEDIA_LNK_FL_IMMUTABLE);1319}1320 1321static void rcsi2_notify_unbind(struct v4l2_async_notifier *notifier,1322 struct v4l2_subdev *subdev,1323 struct v4l2_async_connection *asc)1324{1325 struct rcar_csi2 *priv = notifier_to_csi2(notifier);1326 1327 priv->remote = NULL;1328 1329 dev_dbg(priv->dev, "Unbind %s\n", subdev->name);1330}1331 1332static const struct v4l2_async_notifier_operations rcar_csi2_notify_ops = {1333 .bound = rcsi2_notify_bound,1334 .unbind = rcsi2_notify_unbind,1335};1336 1337static int rcsi2_parse_v4l2(struct rcar_csi2 *priv,1338 struct v4l2_fwnode_endpoint *vep)1339{1340 unsigned int i;1341 1342 /* Only port 0 endpoint 0 is valid. */1343 if (vep->base.port || vep->base.id)1344 return -ENOTCONN;1345 1346 priv->lanes = vep->bus.mipi_csi2.num_data_lanes;1347 1348 switch (vep->bus_type) {1349 case V4L2_MBUS_CSI2_DPHY:1350 if (!priv->info->support_dphy) {1351 dev_err(priv->dev, "D-PHY not supported\n");1352 return -EINVAL;1353 }1354 1355 if (priv->lanes != 1 && priv->lanes != 2 && priv->lanes != 4) {1356 dev_err(priv->dev,1357 "Unsupported number of data-lanes for D-PHY: %u\n",1358 priv->lanes);1359 return -EINVAL;1360 }1361 1362 priv->cphy = false;1363 break;1364 case V4L2_MBUS_CSI2_CPHY:1365 if (!priv->info->support_cphy) {1366 dev_err(priv->dev, "C-PHY not supported\n");1367 return -EINVAL;1368 }1369 1370 if (priv->lanes != 3) {1371 dev_err(priv->dev,1372 "Unsupported number of data-lanes for C-PHY: %u\n",1373 priv->lanes);1374 return -EINVAL;1375 }1376 1377 priv->cphy = true;1378 break;1379 default:1380 dev_err(priv->dev, "Unsupported bus: %u\n", vep->bus_type);1381 return -EINVAL;1382 }1383 1384 for (i = 0; i < ARRAY_SIZE(priv->lane_swap); i++) {1385 priv->lane_swap[i] = i < priv->lanes ?1386 vep->bus.mipi_csi2.data_lanes[i] : i;1387 1388 /* Check for valid lane number. */1389 if (priv->lane_swap[i] < 1 || priv->lane_swap[i] > 4) {1390 dev_err(priv->dev, "data-lanes must be in 1-4 range\n");1391 return -EINVAL;1392 }1393 }1394 1395 return 0;1396}1397 1398static int rcsi2_parse_dt(struct rcar_csi2 *priv)1399{1400 struct v4l2_async_connection *asc;1401 struct fwnode_handle *fwnode;1402 struct fwnode_handle *ep;1403 struct v4l2_fwnode_endpoint v4l2_ep = {1404 .bus_type = V4L2_MBUS_UNKNOWN,1405 };1406 int ret;1407 1408 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(priv->dev), 0, 0, 0);1409 if (!ep) {1410 dev_err(priv->dev, "Not connected to subdevice\n");1411 return -EINVAL;1412 }1413 1414 ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep);1415 if (ret) {1416 dev_err(priv->dev, "Could not parse v4l2 endpoint\n");1417 fwnode_handle_put(ep);1418 return -EINVAL;1419 }1420 1421 ret = rcsi2_parse_v4l2(priv, &v4l2_ep);1422 if (ret) {1423 fwnode_handle_put(ep);1424 return ret;1425 }1426 1427 fwnode = fwnode_graph_get_remote_endpoint(ep);1428 fwnode_handle_put(ep);1429 1430 dev_dbg(priv->dev, "Found '%pOF'\n", to_of_node(fwnode));1431 1432 v4l2_async_subdev_nf_init(&priv->notifier, &priv->subdev);1433 priv->notifier.ops = &rcar_csi2_notify_ops;1434 1435 asc = v4l2_async_nf_add_fwnode(&priv->notifier, fwnode,1436 struct v4l2_async_connection);1437 fwnode_handle_put(fwnode);1438 if (IS_ERR(asc))1439 return PTR_ERR(asc);1440 1441 ret = v4l2_async_nf_register(&priv->notifier);1442 if (ret)1443 v4l2_async_nf_cleanup(&priv->notifier);1444 1445 return ret;1446}1447 1448/* -----------------------------------------------------------------------------1449 * PHTW initialization sequences.1450 *1451 * NOTE: Magic values are from the datasheet and lack documentation.1452 */1453 1454static int rcsi2_phtw_write(struct rcar_csi2 *priv, u16 data, u16 code)1455{1456 unsigned int timeout;1457 1458 rcsi2_write(priv, PHTW_REG,1459 PHTW_DWEN | PHTW_TESTDIN_DATA(data) |1460 PHTW_CWEN | PHTW_TESTDIN_CODE(code));1461 1462 /* Wait for DWEN and CWEN to be cleared by hardware. */1463 for (timeout = 0; timeout <= 20; timeout++) {1464 if (!(rcsi2_read(priv, PHTW_REG) & (PHTW_DWEN | PHTW_CWEN)))1465 return 0;1466 1467 usleep_range(1000, 2000);1468 }1469 1470 dev_err(priv->dev, "Timeout waiting for PHTW_DWEN and/or PHTW_CWEN\n");1471 1472 return -ETIMEDOUT;1473}1474 1475static int rcsi2_phtw_write_array(struct rcar_csi2 *priv,1476 const struct phtw_value *values)1477{1478 const struct phtw_value *value;1479 int ret;1480 1481 for (value = values; value->data || value->code; value++) {1482 ret = rcsi2_phtw_write(priv, value->data, value->code);1483 if (ret)1484 return ret;1485 }1486 1487 return 0;1488}1489 1490static int rcsi2_phtw_write_mbps(struct rcar_csi2 *priv, unsigned int mbps,1491 const struct rcsi2_mbps_reg *values, u16 code)1492{1493 const struct rcsi2_mbps_reg *value;1494 const struct rcsi2_mbps_reg *prev_value = NULL;1495 1496 for (value = values; value->mbps; value++) {1497 if (value->mbps >= mbps)1498 break;1499 prev_value = value;1500 }1501 1502 if (prev_value &&1503 ((mbps - prev_value->mbps) <= (value->mbps - mbps)))1504 value = prev_value;1505 1506 if (!value->mbps) {1507 dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps);1508 return -ERANGE;1509 }1510 1511 return rcsi2_phtw_write(priv, value->reg, code);1512}1513 1514static int __rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv,1515 unsigned int mbps)1516{1517 static const struct phtw_value step1[] = {1518 { .data = 0xcc, .code = 0xe2 },1519 { .data = 0x01, .code = 0xe3 },1520 { .data = 0x11, .code = 0xe4 },1521 { .data = 0x01, .code = 0xe5 },1522 { .data = 0x10, .code = 0x04 },1523 { /* sentinel */ },1524 };1525 1526 static const struct phtw_value step2[] = {1527 { .data = 0x38, .code = 0x08 },1528 { .data = 0x01, .code = 0x00 },1529 { .data = 0x4b, .code = 0xac },1530 { .data = 0x03, .code = 0x00 },1531 { .data = 0x80, .code = 0x07 },1532 { /* sentinel */ },1533 };1534 1535 int ret;1536 1537 ret = rcsi2_phtw_write_array(priv, step1);1538 if (ret)1539 return ret;1540 1541 if (mbps != 0 && mbps <= 250) {1542 ret = rcsi2_phtw_write(priv, 0x39, 0x05);1543 if (ret)1544 return ret;1545 1546 ret = rcsi2_phtw_write_mbps(priv, mbps, phtw_mbps_h3_v3h_m3n,1547 0xf1);1548 if (ret)1549 return ret;1550 }1551 1552 return rcsi2_phtw_write_array(priv, step2);1553}1554 1555static int rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv, unsigned int mbps)1556{1557 return __rcsi2_init_phtw_h3_v3h_m3n(priv, mbps);1558}1559 1560static int rcsi2_init_phtw_h3es2(struct rcar_csi2 *priv, unsigned int mbps)1561{1562 return __rcsi2_init_phtw_h3_v3h_m3n(priv, 0);1563}1564 1565static int rcsi2_init_phtw_v3m_e3(struct rcar_csi2 *priv, unsigned int mbps)1566{1567 return rcsi2_phtw_write_mbps(priv, mbps, phtw_mbps_v3m_e3, 0x44);1568}1569 1570static int rcsi2_phy_post_init_v3m_e3(struct rcar_csi2 *priv)1571{1572 static const struct phtw_value step1[] = {1573 { .data = 0xee, .code = 0x34 },1574 { .data = 0xee, .code = 0x44 },1575 { .data = 0xee, .code = 0x54 },1576 { .data = 0xee, .code = 0x84 },1577 { .data = 0xee, .code = 0x94 },1578 { /* sentinel */ },1579 };1580 1581 return rcsi2_phtw_write_array(priv, step1);1582}1583 1584static int rcsi2_init_phtw_v3u(struct rcar_csi2 *priv,1585 unsigned int mbps)1586{1587 /* In case of 1500Mbps or less */1588 static const struct phtw_value step1[] = {1589 { .data = 0xcc, .code = 0xe2 },1590 { /* sentinel */ },1591 };1592 1593 static const struct phtw_value step2[] = {1594 { .data = 0x01, .code = 0xe3 },1595 { .data = 0x11, .code = 0xe4 },1596 { .data = 0x01, .code = 0xe5 },1597 { /* sentinel */ },1598 };1599 1600 /* In case of 1500Mbps or less */1601 static const struct phtw_value step3[] = {1602 { .data = 0x38, .code = 0x08 },1603 { /* sentinel */ },1604 };1605 1606 static const struct phtw_value step4[] = {1607 { .data = 0x01, .code = 0x00 },1608 { .data = 0x4b, .code = 0xac },1609 { .data = 0x03, .code = 0x00 },1610 { .data = 0x80, .code = 0x07 },1611 { /* sentinel */ },1612 };1613 1614 int ret;1615 1616 if (mbps != 0 && mbps <= 1500)1617 ret = rcsi2_phtw_write_array(priv, step1);1618 else1619 ret = rcsi2_phtw_write_mbps(priv, mbps, phtw_mbps_v3u, 0xe2);1620 if (ret)1621 return ret;1622 1623 ret = rcsi2_phtw_write_array(priv, step2);1624 if (ret)1625 return ret;1626 1627 if (mbps != 0 && mbps <= 1500) {1628 ret = rcsi2_phtw_write_array(priv, step3);1629 if (ret)1630 return ret;1631 }1632 1633 ret = rcsi2_phtw_write_array(priv, step4);1634 if (ret)1635 return ret;1636 1637 return ret;1638}1639 1640/* -----------------------------------------------------------------------------1641 * Platform Device Driver.1642 */1643 1644static int rcsi2_link_setup(struct media_entity *entity,1645 const struct media_pad *local,1646 const struct media_pad *remote, u32 flags)1647{1648 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);1649 struct rcar_csi2 *priv = sd_to_csi2(sd);1650 struct video_device *vdev;1651 int channel, vc;1652 u32 id;1653 1654 if (!is_media_entity_v4l2_video_device(remote->entity)) {1655 dev_err(priv->dev, "Remote is not a video device\n");1656 return -EINVAL;1657 }1658 1659 vdev = media_entity_to_video_device(remote->entity);1660 1661 if (of_property_read_u32(vdev->dev_parent->of_node, "renesas,id", &id)) {1662 dev_err(priv->dev, "No renesas,id, can't configure routing\n");1663 return -EINVAL;1664 }1665 1666 channel = id % 4;1667 1668 if (flags & MEDIA_LNK_FL_ENABLED) {1669 if (media_pad_remote_pad_first(local)) {1670 dev_dbg(priv->dev,1671 "Each VC can only be routed to one output channel\n");1672 return -EINVAL;1673 }1674 1675 vc = local->index - 1;1676 1677 dev_dbg(priv->dev, "Route VC%d to VIN%u on output channel %d\n",1678 vc, id, channel);1679 } else {1680 vc = -1;1681 }1682 1683 priv->channel_vc[channel] = vc;1684 1685 return 0;1686}1687 1688static const struct media_entity_operations rcar_csi2_entity_ops = {1689 .link_setup = rcsi2_link_setup,1690 .link_validate = v4l2_subdev_link_validate,1691};1692 1693static int rcsi2_probe_resources(struct rcar_csi2 *priv,1694 struct platform_device *pdev)1695{1696 int irq, ret;1697 1698 priv->base = devm_platform_ioremap_resource(pdev, 0);1699 if (IS_ERR(priv->base))1700 return PTR_ERR(priv->base);1701 1702 irq = platform_get_irq(pdev, 0);1703 if (irq < 0)1704 return irq;1705 1706 ret = devm_request_threaded_irq(&pdev->dev, irq, rcsi2_irq,1707 rcsi2_irq_thread, IRQF_SHARED,1708 KBUILD_MODNAME, priv);1709 if (ret)1710 return ret;1711 1712 priv->rstc = devm_reset_control_get(&pdev->dev, NULL);1713 1714 return PTR_ERR_OR_ZERO(priv->rstc);1715}1716 1717static const struct rcar_csi2_info rcar_csi2_info_r8a7795 = {1718 .init_phtw = rcsi2_init_phtw_h3_v3h_m3n,1719 .start_receiver = rcsi2_start_receiver_gen3,1720 .enter_standby = rcsi2_enter_standby_gen3,1721 .hsfreqrange = hsfreqrange_h3_v3h_m3n,1722 .csi0clkfreqrange = 0x20,1723 .num_channels = 4,1724 .clear_ulps = true,1725 .support_dphy = true,1726};1727 1728static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = {1729 .init_phtw = rcsi2_init_phtw_h3es2,1730 .start_receiver = rcsi2_start_receiver_gen3,1731 .enter_standby = rcsi2_enter_standby_gen3,1732 .hsfreqrange = hsfreqrange_h3_v3h_m3n,1733 .csi0clkfreqrange = 0x20,1734 .num_channels = 4,1735 .clear_ulps = true,1736 .support_dphy = true,1737};1738 1739static const struct rcar_csi2_info rcar_csi2_info_r8a7796 = {1740 .start_receiver = rcsi2_start_receiver_gen3,1741 .enter_standby = rcsi2_enter_standby_gen3,1742 .hsfreqrange = hsfreqrange_m3w,1743 .num_channels = 4,1744 .support_dphy = true,1745};1746 1747static const struct rcar_csi2_info rcar_csi2_info_r8a77961 = {1748 .start_receiver = rcsi2_start_receiver_gen3,1749 .enter_standby = rcsi2_enter_standby_gen3,1750 .hsfreqrange = hsfreqrange_m3w,1751 .num_channels = 4,1752 .support_dphy = true,1753};1754 1755static const struct rcar_csi2_info rcar_csi2_info_r8a77965 = {1756 .init_phtw = rcsi2_init_phtw_h3_v3h_m3n,1757 .start_receiver = rcsi2_start_receiver_gen3,1758 .enter_standby = rcsi2_enter_standby_gen3,1759 .hsfreqrange = hsfreqrange_h3_v3h_m3n,1760 .csi0clkfreqrange = 0x20,1761 .num_channels = 4,1762 .clear_ulps = true,1763 .support_dphy = true,1764};1765 1766static const struct rcar_csi2_info rcar_csi2_info_r8a77970 = {1767 .init_phtw = rcsi2_init_phtw_v3m_e3,1768 .phy_post_init = rcsi2_phy_post_init_v3m_e3,1769 .start_receiver = rcsi2_start_receiver_gen3,1770 .enter_standby = rcsi2_enter_standby_gen3,1771 .num_channels = 4,1772 .support_dphy = true,1773};1774 1775static const struct rcar_csi2_info rcar_csi2_info_r8a77980 = {1776 .init_phtw = rcsi2_init_phtw_h3_v3h_m3n,1777 .start_receiver = rcsi2_start_receiver_gen3,1778 .enter_standby = rcsi2_enter_standby_gen3,1779 .hsfreqrange = hsfreqrange_h3_v3h_m3n,1780 .csi0clkfreqrange = 0x20,1781 .clear_ulps = true,1782 .support_dphy = true,1783};1784 1785static const struct rcar_csi2_info rcar_csi2_info_r8a77990 = {1786 .init_phtw = rcsi2_init_phtw_v3m_e3,1787 .phy_post_init = rcsi2_phy_post_init_v3m_e3,1788 .start_receiver = rcsi2_start_receiver_gen3,1789 .enter_standby = rcsi2_enter_standby_gen3,1790 .num_channels = 2,1791 .support_dphy = true,1792};1793 1794static const struct rcar_csi2_info rcar_csi2_info_r8a779a0 = {1795 .init_phtw = rcsi2_init_phtw_v3u,1796 .start_receiver = rcsi2_start_receiver_gen3,1797 .enter_standby = rcsi2_enter_standby_gen3,1798 .hsfreqrange = hsfreqrange_v3u,1799 .csi0clkfreqrange = 0x20,1800 .clear_ulps = true,1801 .use_isp = true,1802 .support_dphy = true,1803};1804 1805static const struct rcar_csi2_info rcar_csi2_info_r8a779g0 = {1806 .start_receiver = rcsi2_start_receiver_v4h,1807 .use_isp = true,1808 .support_cphy = true,1809};1810 1811static const struct of_device_id rcar_csi2_of_table[] = {1812 {1813 .compatible = "renesas,r8a774a1-csi2",1814 .data = &rcar_csi2_info_r8a7796,1815 },1816 {1817 .compatible = "renesas,r8a774b1-csi2",1818 .data = &rcar_csi2_info_r8a77965,1819 },1820 {1821 .compatible = "renesas,r8a774c0-csi2",1822 .data = &rcar_csi2_info_r8a77990,1823 },1824 {1825 .compatible = "renesas,r8a774e1-csi2",1826 .data = &rcar_csi2_info_r8a7795,1827 },1828 {1829 .compatible = "renesas,r8a7795-csi2",1830 .data = &rcar_csi2_info_r8a7795,1831 },1832 {1833 .compatible = "renesas,r8a7796-csi2",1834 .data = &rcar_csi2_info_r8a7796,1835 },1836 {1837 .compatible = "renesas,r8a77961-csi2",1838 .data = &rcar_csi2_info_r8a77961,1839 },1840 {1841 .compatible = "renesas,r8a77965-csi2",1842 .data = &rcar_csi2_info_r8a77965,1843 },1844 {1845 .compatible = "renesas,r8a77970-csi2",1846 .data = &rcar_csi2_info_r8a77970,1847 },1848 {1849 .compatible = "renesas,r8a77980-csi2",1850 .data = &rcar_csi2_info_r8a77980,1851 },1852 {1853 .compatible = "renesas,r8a77990-csi2",1854 .data = &rcar_csi2_info_r8a77990,1855 },1856 {1857 .compatible = "renesas,r8a779a0-csi2",1858 .data = &rcar_csi2_info_r8a779a0,1859 },1860 {1861 .compatible = "renesas,r8a779g0-csi2",1862 .data = &rcar_csi2_info_r8a779g0,1863 },1864 { /* sentinel */ },1865};1866MODULE_DEVICE_TABLE(of, rcar_csi2_of_table);1867 1868static const struct soc_device_attribute r8a7795[] = {1869 {1870 .soc_id = "r8a7795", .revision = "ES2.*",1871 .data = &rcar_csi2_info_r8a7795es2,1872 },1873 { /* sentinel */ }1874};1875 1876static int rcsi2_probe(struct platform_device *pdev)1877{1878 const struct soc_device_attribute *attr;1879 struct rcar_csi2 *priv;1880 unsigned int i, num_pads;1881 int ret;1882 1883 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);1884 if (!priv)1885 return -ENOMEM;1886 1887 priv->info = of_device_get_match_data(&pdev->dev);1888 1889 /*1890 * The different ES versions of r8a7795 (H3) behave differently but1891 * share the same compatible string.1892 */1893 attr = soc_device_match(r8a7795);1894 if (attr)1895 priv->info = attr->data;1896 1897 priv->dev = &pdev->dev;1898 1899 priv->stream_count = 0;1900 1901 ret = rcsi2_probe_resources(priv, pdev);1902 if (ret) {1903 dev_err(priv->dev, "Failed to get resources\n");1904 return ret;1905 }1906 1907 platform_set_drvdata(pdev, priv);1908 1909 ret = rcsi2_parse_dt(priv);1910 if (ret)1911 return ret;1912 1913 priv->subdev.owner = THIS_MODULE;1914 priv->subdev.dev = &pdev->dev;1915 priv->subdev.internal_ops = &rcar_csi2_internal_ops;1916 v4l2_subdev_init(&priv->subdev, &rcar_csi2_subdev_ops);1917 v4l2_set_subdevdata(&priv->subdev, &pdev->dev);1918 snprintf(priv->subdev.name, sizeof(priv->subdev.name), "%s %s",1919 KBUILD_MODNAME, dev_name(&pdev->dev));1920 priv->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;1921 1922 priv->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;1923 priv->subdev.entity.ops = &rcar_csi2_entity_ops;1924 1925 num_pads = rcsi2_num_pads(priv);1926 1927 priv->pads[RCAR_CSI2_SINK].flags = MEDIA_PAD_FL_SINK;1928 for (i = RCAR_CSI2_SOURCE_VC0; i < num_pads; i++)1929 priv->pads[i].flags = MEDIA_PAD_FL_SOURCE;1930 1931 ret = media_entity_pads_init(&priv->subdev.entity, num_pads,1932 priv->pads);1933 if (ret)1934 goto error_async;1935 1936 for (i = 0; i < ARRAY_SIZE(priv->channel_vc); i++)1937 priv->channel_vc[i] = -1;1938 1939 pm_runtime_enable(&pdev->dev);1940 1941 ret = v4l2_subdev_init_finalize(&priv->subdev);1942 if (ret)1943 goto error_pm_runtime;1944 1945 ret = v4l2_async_register_subdev(&priv->subdev);1946 if (ret < 0)1947 goto error_subdev;1948 1949 dev_info(priv->dev, "%d lanes found\n", priv->lanes);1950 1951 return 0;1952 1953error_subdev:1954 v4l2_subdev_cleanup(&priv->subdev);1955error_pm_runtime:1956 pm_runtime_disable(&pdev->dev);1957error_async:1958 v4l2_async_nf_unregister(&priv->notifier);1959 v4l2_async_nf_cleanup(&priv->notifier);1960 1961 return ret;1962}1963 1964static void rcsi2_remove(struct platform_device *pdev)1965{1966 struct rcar_csi2 *priv = platform_get_drvdata(pdev);1967 1968 v4l2_async_nf_unregister(&priv->notifier);1969 v4l2_async_nf_cleanup(&priv->notifier);1970 v4l2_async_unregister_subdev(&priv->subdev);1971 v4l2_subdev_cleanup(&priv->subdev);1972 1973 pm_runtime_disable(&pdev->dev);1974}1975 1976static struct platform_driver rcar_csi2_pdrv = {1977 .remove_new = rcsi2_remove,1978 .probe = rcsi2_probe,1979 .driver = {1980 .name = "rcar-csi2",1981 .suppress_bind_attrs = true,1982 .of_match_table = rcar_csi2_of_table,1983 },1984};1985 1986module_platform_driver(rcar_csi2_pdrv);1987 1988MODULE_AUTHOR("Niklas Söderlund <niklas.soderlund@ragnatech.se>");1989MODULE_DESCRIPTION("Renesas R-Car MIPI CSI-2 receiver driver");1990MODULE_LICENSE("GPL");1991