1dec72739SThierry Reding /* 2dec72739SThierry Reding * Copyright (C) 2013 NVIDIA Corporation 3dec72739SThierry Reding * 49a2ac2dcSThierry Reding * This program is free software; you can redistribute it and/or modify 59a2ac2dcSThierry Reding * it under the terms of the GNU General Public License version 2 as 69a2ac2dcSThierry Reding * published by the Free Software Foundation. 7dec72739SThierry Reding */ 8dec72739SThierry Reding 9dec72739SThierry Reding #include <linux/clk.h> 10dec72739SThierry Reding #include <linux/debugfs.h> 11dec72739SThierry Reding #include <linux/host1x.h> 12dec72739SThierry Reding #include <linux/module.h> 13dec72739SThierry Reding #include <linux/of.h> 14e94236cdSThierry Reding #include <linux/of_platform.h> 15dec72739SThierry Reding #include <linux/platform_device.h> 16dec72739SThierry Reding #include <linux/reset.h> 17dec72739SThierry Reding 183b077afbSThierry Reding #include <linux/regulator/consumer.h> 193b077afbSThierry Reding 20*4aa3df71SThierry Reding #include <drm/drm_atomic_helper.h> 21dec72739SThierry Reding #include <drm/drm_mipi_dsi.h> 22dec72739SThierry Reding #include <drm/drm_panel.h> 23dec72739SThierry Reding 24dec72739SThierry Reding #include <video/mipi_display.h> 25dec72739SThierry Reding 26dec72739SThierry Reding #include "dc.h" 27dec72739SThierry Reding #include "drm.h" 28dec72739SThierry Reding #include "dsi.h" 29dec72739SThierry Reding #include "mipi-phy.h" 30dec72739SThierry Reding 31dec72739SThierry Reding struct tegra_dsi { 32dec72739SThierry Reding struct host1x_client client; 33dec72739SThierry Reding struct tegra_output output; 34dec72739SThierry Reding struct device *dev; 35dec72739SThierry Reding 36dec72739SThierry Reding void __iomem *regs; 37dec72739SThierry Reding 38dec72739SThierry Reding struct reset_control *rst; 39dec72739SThierry Reding struct clk *clk_parent; 40dec72739SThierry Reding struct clk *clk_lp; 41dec72739SThierry Reding struct clk *clk; 42dec72739SThierry Reding 43dec72739SThierry Reding struct drm_info_list *debugfs_files; 44dec72739SThierry Reding struct drm_minor *minor; 45dec72739SThierry Reding struct dentry *debugfs; 46dec72739SThierry Reding 4717297a28SThierry Reding unsigned long flags; 48dec72739SThierry Reding enum mipi_dsi_pixel_format format; 49dec72739SThierry Reding unsigned int lanes; 50dec72739SThierry Reding 51dec72739SThierry Reding struct tegra_mipi_device *mipi; 52dec72739SThierry Reding struct mipi_dsi_host host; 533b077afbSThierry Reding 543b077afbSThierry Reding struct regulator *vdd; 55976cebc3SThierry Reding 56976cebc3SThierry Reding unsigned int video_fifo_depth; 57976cebc3SThierry Reding unsigned int host_fifo_depth; 58e94236cdSThierry Reding 59e94236cdSThierry Reding /* for ganged-mode support */ 60e94236cdSThierry Reding struct tegra_dsi *master; 61e94236cdSThierry Reding struct tegra_dsi *slave; 62dec72739SThierry Reding }; 63dec72739SThierry Reding 64dec72739SThierry Reding static inline struct tegra_dsi * 65dec72739SThierry Reding host1x_client_to_dsi(struct host1x_client *client) 66dec72739SThierry Reding { 67dec72739SThierry Reding return container_of(client, struct tegra_dsi, client); 68dec72739SThierry Reding } 69dec72739SThierry Reding 70dec72739SThierry Reding static inline struct tegra_dsi *host_to_tegra(struct mipi_dsi_host *host) 71dec72739SThierry Reding { 72dec72739SThierry Reding return container_of(host, struct tegra_dsi, host); 73dec72739SThierry Reding } 74dec72739SThierry Reding 75dec72739SThierry Reding static inline struct tegra_dsi *to_dsi(struct tegra_output *output) 76dec72739SThierry Reding { 77dec72739SThierry Reding return container_of(output, struct tegra_dsi, output); 78dec72739SThierry Reding } 79dec72739SThierry Reding 809c0b4ca1SThierry Reding static inline u32 tegra_dsi_readl(struct tegra_dsi *dsi, unsigned long reg) 81dec72739SThierry Reding { 82dec72739SThierry Reding return readl(dsi->regs + (reg << 2)); 83dec72739SThierry Reding } 84dec72739SThierry Reding 859c0b4ca1SThierry Reding static inline void tegra_dsi_writel(struct tegra_dsi *dsi, u32 value, 86dec72739SThierry Reding unsigned long reg) 87dec72739SThierry Reding { 88dec72739SThierry Reding writel(value, dsi->regs + (reg << 2)); 89dec72739SThierry Reding } 90dec72739SThierry Reding 91dec72739SThierry Reding static int tegra_dsi_show_regs(struct seq_file *s, void *data) 92dec72739SThierry Reding { 93dec72739SThierry Reding struct drm_info_node *node = s->private; 94dec72739SThierry Reding struct tegra_dsi *dsi = node->info_ent->data; 95dec72739SThierry Reding 96dec72739SThierry Reding #define DUMP_REG(name) \ 979c0b4ca1SThierry Reding seq_printf(s, "%-32s %#05x %08x\n", #name, name, \ 98dec72739SThierry Reding tegra_dsi_readl(dsi, name)) 99dec72739SThierry Reding 100dec72739SThierry Reding DUMP_REG(DSI_INCR_SYNCPT); 101dec72739SThierry Reding DUMP_REG(DSI_INCR_SYNCPT_CONTROL); 102dec72739SThierry Reding DUMP_REG(DSI_INCR_SYNCPT_ERROR); 103dec72739SThierry Reding DUMP_REG(DSI_CTXSW); 104dec72739SThierry Reding DUMP_REG(DSI_RD_DATA); 105dec72739SThierry Reding DUMP_REG(DSI_WR_DATA); 106dec72739SThierry Reding DUMP_REG(DSI_POWER_CONTROL); 107dec72739SThierry Reding DUMP_REG(DSI_INT_ENABLE); 108dec72739SThierry Reding DUMP_REG(DSI_INT_STATUS); 109dec72739SThierry Reding DUMP_REG(DSI_INT_MASK); 110dec72739SThierry Reding DUMP_REG(DSI_HOST_CONTROL); 111dec72739SThierry Reding DUMP_REG(DSI_CONTROL); 112dec72739SThierry Reding DUMP_REG(DSI_SOL_DELAY); 113dec72739SThierry Reding DUMP_REG(DSI_MAX_THRESHOLD); 114dec72739SThierry Reding DUMP_REG(DSI_TRIGGER); 115dec72739SThierry Reding DUMP_REG(DSI_TX_CRC); 116dec72739SThierry Reding DUMP_REG(DSI_STATUS); 117dec72739SThierry Reding 118dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_CONTROL); 119dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_0); 120dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_1); 121dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_2); 122dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_3); 123dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_4); 124dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_5); 125dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_6); 126dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_7); 127dec72739SThierry Reding 128dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_0_LO); 129dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_0_HI); 130dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_1_LO); 131dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_1_HI); 132dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_2_LO); 133dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_2_HI); 134dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_3_LO); 135dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_3_HI); 136dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_4_LO); 137dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_4_HI); 138dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_5_LO); 139dec72739SThierry Reding DUMP_REG(DSI_PKT_SEQ_5_HI); 140dec72739SThierry Reding 141dec72739SThierry Reding DUMP_REG(DSI_DCS_CMDS); 142dec72739SThierry Reding 143dec72739SThierry Reding DUMP_REG(DSI_PKT_LEN_0_1); 144dec72739SThierry Reding DUMP_REG(DSI_PKT_LEN_2_3); 145dec72739SThierry Reding DUMP_REG(DSI_PKT_LEN_4_5); 146dec72739SThierry Reding DUMP_REG(DSI_PKT_LEN_6_7); 147dec72739SThierry Reding 148dec72739SThierry Reding DUMP_REG(DSI_PHY_TIMING_0); 149dec72739SThierry Reding DUMP_REG(DSI_PHY_TIMING_1); 150dec72739SThierry Reding DUMP_REG(DSI_PHY_TIMING_2); 151dec72739SThierry Reding DUMP_REG(DSI_BTA_TIMING); 152dec72739SThierry Reding 153dec72739SThierry Reding DUMP_REG(DSI_TIMEOUT_0); 154dec72739SThierry Reding DUMP_REG(DSI_TIMEOUT_1); 155dec72739SThierry Reding DUMP_REG(DSI_TO_TALLY); 156dec72739SThierry Reding 157dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_0); 158dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_CD); 159dec72739SThierry Reding DUMP_REG(DSI_PAD_CD_STATUS); 160dec72739SThierry Reding DUMP_REG(DSI_VIDEO_MODE_CONTROL); 161dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_1); 162dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_2); 163dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_3); 164dec72739SThierry Reding DUMP_REG(DSI_PAD_CONTROL_4); 165dec72739SThierry Reding 166dec72739SThierry Reding DUMP_REG(DSI_GANGED_MODE_CONTROL); 167dec72739SThierry Reding DUMP_REG(DSI_GANGED_MODE_START); 168dec72739SThierry Reding DUMP_REG(DSI_GANGED_MODE_SIZE); 169dec72739SThierry Reding 170dec72739SThierry Reding DUMP_REG(DSI_RAW_DATA_BYTE_COUNT); 171dec72739SThierry Reding DUMP_REG(DSI_ULTRA_LOW_POWER_CONTROL); 172dec72739SThierry Reding 173dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_8); 174dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_9); 175dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_10); 176dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_11); 177dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_12); 178dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_13); 179dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_14); 180dec72739SThierry Reding DUMP_REG(DSI_INIT_SEQ_DATA_15); 181dec72739SThierry Reding 182dec72739SThierry Reding #undef DUMP_REG 183dec72739SThierry Reding 184dec72739SThierry Reding return 0; 185dec72739SThierry Reding } 186dec72739SThierry Reding 187dec72739SThierry Reding static struct drm_info_list debugfs_files[] = { 188dec72739SThierry Reding { "regs", tegra_dsi_show_regs, 0, NULL }, 189dec72739SThierry Reding }; 190dec72739SThierry Reding 191dec72739SThierry Reding static int tegra_dsi_debugfs_init(struct tegra_dsi *dsi, 192dec72739SThierry Reding struct drm_minor *minor) 193dec72739SThierry Reding { 194dec72739SThierry Reding const char *name = dev_name(dsi->dev); 195dec72739SThierry Reding unsigned int i; 196dec72739SThierry Reding int err; 197dec72739SThierry Reding 198dec72739SThierry Reding dsi->debugfs = debugfs_create_dir(name, minor->debugfs_root); 199dec72739SThierry Reding if (!dsi->debugfs) 200dec72739SThierry Reding return -ENOMEM; 201dec72739SThierry Reding 202dec72739SThierry Reding dsi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files), 203dec72739SThierry Reding GFP_KERNEL); 204dec72739SThierry Reding if (!dsi->debugfs_files) { 205dec72739SThierry Reding err = -ENOMEM; 206dec72739SThierry Reding goto remove; 207dec72739SThierry Reding } 208dec72739SThierry Reding 209dec72739SThierry Reding for (i = 0; i < ARRAY_SIZE(debugfs_files); i++) 210dec72739SThierry Reding dsi->debugfs_files[i].data = dsi; 211dec72739SThierry Reding 212dec72739SThierry Reding err = drm_debugfs_create_files(dsi->debugfs_files, 213dec72739SThierry Reding ARRAY_SIZE(debugfs_files), 214dec72739SThierry Reding dsi->debugfs, minor); 215dec72739SThierry Reding if (err < 0) 216dec72739SThierry Reding goto free; 217dec72739SThierry Reding 218dec72739SThierry Reding dsi->minor = minor; 219dec72739SThierry Reding 220dec72739SThierry Reding return 0; 221dec72739SThierry Reding 222dec72739SThierry Reding free: 223dec72739SThierry Reding kfree(dsi->debugfs_files); 224dec72739SThierry Reding dsi->debugfs_files = NULL; 225dec72739SThierry Reding remove: 226dec72739SThierry Reding debugfs_remove(dsi->debugfs); 227dec72739SThierry Reding dsi->debugfs = NULL; 228dec72739SThierry Reding 229dec72739SThierry Reding return err; 230dec72739SThierry Reding } 231dec72739SThierry Reding 2324009c224SThierry Reding static void tegra_dsi_debugfs_exit(struct tegra_dsi *dsi) 233dec72739SThierry Reding { 234dec72739SThierry Reding drm_debugfs_remove_files(dsi->debugfs_files, ARRAY_SIZE(debugfs_files), 235dec72739SThierry Reding dsi->minor); 236dec72739SThierry Reding dsi->minor = NULL; 237dec72739SThierry Reding 238dec72739SThierry Reding kfree(dsi->debugfs_files); 239dec72739SThierry Reding dsi->debugfs_files = NULL; 240dec72739SThierry Reding 241dec72739SThierry Reding debugfs_remove(dsi->debugfs); 242dec72739SThierry Reding dsi->debugfs = NULL; 243dec72739SThierry Reding } 244dec72739SThierry Reding 245dec72739SThierry Reding #define PKT_ID0(id) ((((id) & 0x3f) << 3) | (1 << 9)) 246dec72739SThierry Reding #define PKT_LEN0(len) (((len) & 0x07) << 0) 247dec72739SThierry Reding #define PKT_ID1(id) ((((id) & 0x3f) << 13) | (1 << 19)) 248dec72739SThierry Reding #define PKT_LEN1(len) (((len) & 0x07) << 10) 249dec72739SThierry Reding #define PKT_ID2(id) ((((id) & 0x3f) << 23) | (1 << 29)) 250dec72739SThierry Reding #define PKT_LEN2(len) (((len) & 0x07) << 20) 251dec72739SThierry Reding 252dec72739SThierry Reding #define PKT_LP (1 << 30) 253dec72739SThierry Reding #define NUM_PKT_SEQ 12 254dec72739SThierry Reding 25517297a28SThierry Reding /* 25617297a28SThierry Reding * non-burst mode with sync pulses 25717297a28SThierry Reding */ 25817297a28SThierry Reding static const u32 pkt_seq_video_non_burst_sync_pulses[NUM_PKT_SEQ] = { 259dec72739SThierry Reding [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) | 260dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 261dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 262dec72739SThierry Reding PKT_LP, 263dec72739SThierry Reding [ 1] = 0, 264dec72739SThierry Reding [ 2] = PKT_ID0(MIPI_DSI_V_SYNC_END) | PKT_LEN0(0) | 265dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 266dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 267dec72739SThierry Reding PKT_LP, 268dec72739SThierry Reding [ 3] = 0, 269dec72739SThierry Reding [ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 270dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 271dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 272dec72739SThierry Reding PKT_LP, 273dec72739SThierry Reding [ 5] = 0, 274dec72739SThierry Reding [ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 275dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 276dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0), 277dec72739SThierry Reding [ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) | 278dec72739SThierry Reding PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) | 279dec72739SThierry Reding PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4), 280dec72739SThierry Reding [ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 281dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 282dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | 283dec72739SThierry Reding PKT_LP, 284dec72739SThierry Reding [ 9] = 0, 285dec72739SThierry Reding [10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 286dec72739SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | 287dec72739SThierry Reding PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0), 288dec72739SThierry Reding [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) | 289dec72739SThierry Reding PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) | 290dec72739SThierry Reding PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4), 291dec72739SThierry Reding }; 292dec72739SThierry Reding 29317297a28SThierry Reding /* 29417297a28SThierry Reding * non-burst mode with sync events 29517297a28SThierry Reding */ 29617297a28SThierry Reding static const u32 pkt_seq_video_non_burst_sync_events[NUM_PKT_SEQ] = { 29717297a28SThierry Reding [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) | 29817297a28SThierry Reding PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | 29917297a28SThierry Reding PKT_LP, 30017297a28SThierry Reding [ 1] = 0, 30117297a28SThierry Reding [ 2] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 30217297a28SThierry Reding PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | 30317297a28SThierry Reding PKT_LP, 30417297a28SThierry Reding [ 3] = 0, 30517297a28SThierry Reding [ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 30617297a28SThierry Reding PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | 30717297a28SThierry Reding PKT_LP, 30817297a28SThierry Reding [ 5] = 0, 30917297a28SThierry Reding [ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 31017297a28SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) | 31117297a28SThierry Reding PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3), 31217297a28SThierry Reding [ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4), 31317297a28SThierry Reding [ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 31417297a28SThierry Reding PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | 31517297a28SThierry Reding PKT_LP, 31617297a28SThierry Reding [ 9] = 0, 31717297a28SThierry Reding [10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | 31817297a28SThierry Reding PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) | 31917297a28SThierry Reding PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3), 32017297a28SThierry Reding [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4), 32117297a28SThierry Reding }; 32217297a28SThierry Reding 323337b443dSThierry Reding static const u32 pkt_seq_command_mode[NUM_PKT_SEQ] = { 324337b443dSThierry Reding [ 0] = 0, 325337b443dSThierry Reding [ 1] = 0, 326337b443dSThierry Reding [ 2] = 0, 327337b443dSThierry Reding [ 3] = 0, 328337b443dSThierry Reding [ 4] = 0, 329337b443dSThierry Reding [ 5] = 0, 330337b443dSThierry Reding [ 6] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(3) | PKT_LP, 331337b443dSThierry Reding [ 7] = 0, 332337b443dSThierry Reding [ 8] = 0, 333337b443dSThierry Reding [ 9] = 0, 334337b443dSThierry Reding [10] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(5) | PKT_LP, 335337b443dSThierry Reding [11] = 0, 336337b443dSThierry Reding }; 337337b443dSThierry Reding 338dec72739SThierry Reding static int tegra_dsi_set_phy_timing(struct tegra_dsi *dsi) 339dec72739SThierry Reding { 340dec72739SThierry Reding struct mipi_dphy_timing timing; 3419c0b4ca1SThierry Reding unsigned long period; 3429c0b4ca1SThierry Reding u32 value; 343dec72739SThierry Reding long rate; 344dec72739SThierry Reding int err; 345dec72739SThierry Reding 346dec72739SThierry Reding rate = clk_get_rate(dsi->clk); 347dec72739SThierry Reding if (rate < 0) 348dec72739SThierry Reding return rate; 349dec72739SThierry Reding 350369bc65bSThierry Reding period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, rate * 2); 351dec72739SThierry Reding 352dec72739SThierry Reding err = mipi_dphy_timing_get_default(&timing, period); 353dec72739SThierry Reding if (err < 0) 354dec72739SThierry Reding return err; 355dec72739SThierry Reding 356dec72739SThierry Reding err = mipi_dphy_timing_validate(&timing, period); 357dec72739SThierry Reding if (err < 0) { 358dec72739SThierry Reding dev_err(dsi->dev, "failed to validate D-PHY timing: %d\n", err); 359dec72739SThierry Reding return err; 360dec72739SThierry Reding } 361dec72739SThierry Reding 362dec72739SThierry Reding /* 363dec72739SThierry Reding * The D-PHY timing fields below are expressed in byte-clock cycles, 364dec72739SThierry Reding * so multiply the period by 8. 365dec72739SThierry Reding */ 366dec72739SThierry Reding period *= 8; 367dec72739SThierry Reding 368dec72739SThierry Reding value = DSI_TIMING_FIELD(timing.hsexit, period, 1) << 24 | 369dec72739SThierry Reding DSI_TIMING_FIELD(timing.hstrail, period, 0) << 16 | 370dec72739SThierry Reding DSI_TIMING_FIELD(timing.hszero, period, 3) << 8 | 371dec72739SThierry Reding DSI_TIMING_FIELD(timing.hsprepare, period, 1); 372dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_0); 373dec72739SThierry Reding 374dec72739SThierry Reding value = DSI_TIMING_FIELD(timing.clktrail, period, 1) << 24 | 375dec72739SThierry Reding DSI_TIMING_FIELD(timing.clkpost, period, 1) << 16 | 376dec72739SThierry Reding DSI_TIMING_FIELD(timing.clkzero, period, 1) << 8 | 377dec72739SThierry Reding DSI_TIMING_FIELD(timing.lpx, period, 1); 378dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_1); 379dec72739SThierry Reding 380dec72739SThierry Reding value = DSI_TIMING_FIELD(timing.clkprepare, period, 1) << 16 | 381dec72739SThierry Reding DSI_TIMING_FIELD(timing.clkpre, period, 1) << 8 | 382dec72739SThierry Reding DSI_TIMING_FIELD(0xff * period, period, 0) << 0; 383dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_2); 384dec72739SThierry Reding 385dec72739SThierry Reding value = DSI_TIMING_FIELD(timing.taget, period, 1) << 16 | 386dec72739SThierry Reding DSI_TIMING_FIELD(timing.tasure, period, 1) << 8 | 387dec72739SThierry Reding DSI_TIMING_FIELD(timing.tago, period, 1); 388dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_BTA_TIMING); 389dec72739SThierry Reding 3907e3bc3a9SSean Paul if (dsi->slave) 3917e3bc3a9SSean Paul return tegra_dsi_set_phy_timing(dsi->slave); 3927e3bc3a9SSean Paul 393dec72739SThierry Reding return 0; 394dec72739SThierry Reding } 395dec72739SThierry Reding 396dec72739SThierry Reding static int tegra_dsi_get_muldiv(enum mipi_dsi_pixel_format format, 397dec72739SThierry Reding unsigned int *mulp, unsigned int *divp) 398dec72739SThierry Reding { 399dec72739SThierry Reding switch (format) { 400dec72739SThierry Reding case MIPI_DSI_FMT_RGB666_PACKED: 401dec72739SThierry Reding case MIPI_DSI_FMT_RGB888: 402dec72739SThierry Reding *mulp = 3; 403dec72739SThierry Reding *divp = 1; 404dec72739SThierry Reding break; 405dec72739SThierry Reding 406dec72739SThierry Reding case MIPI_DSI_FMT_RGB565: 407dec72739SThierry Reding *mulp = 2; 408dec72739SThierry Reding *divp = 1; 409dec72739SThierry Reding break; 410dec72739SThierry Reding 411dec72739SThierry Reding case MIPI_DSI_FMT_RGB666: 412dec72739SThierry Reding *mulp = 9; 413dec72739SThierry Reding *divp = 4; 414dec72739SThierry Reding break; 415dec72739SThierry Reding 416dec72739SThierry Reding default: 417dec72739SThierry Reding return -EINVAL; 418dec72739SThierry Reding } 419dec72739SThierry Reding 420dec72739SThierry Reding return 0; 421dec72739SThierry Reding } 422dec72739SThierry Reding 423f7d6889bSThierry Reding static int tegra_dsi_get_format(enum mipi_dsi_pixel_format format, 424f7d6889bSThierry Reding enum tegra_dsi_format *fmt) 425f7d6889bSThierry Reding { 426f7d6889bSThierry Reding switch (format) { 427f7d6889bSThierry Reding case MIPI_DSI_FMT_RGB888: 428f7d6889bSThierry Reding *fmt = TEGRA_DSI_FORMAT_24P; 429f7d6889bSThierry Reding break; 430f7d6889bSThierry Reding 431f7d6889bSThierry Reding case MIPI_DSI_FMT_RGB666: 432f7d6889bSThierry Reding *fmt = TEGRA_DSI_FORMAT_18NP; 433f7d6889bSThierry Reding break; 434f7d6889bSThierry Reding 435f7d6889bSThierry Reding case MIPI_DSI_FMT_RGB666_PACKED: 436f7d6889bSThierry Reding *fmt = TEGRA_DSI_FORMAT_18P; 437f7d6889bSThierry Reding break; 438f7d6889bSThierry Reding 439f7d6889bSThierry Reding case MIPI_DSI_FMT_RGB565: 440f7d6889bSThierry Reding *fmt = TEGRA_DSI_FORMAT_16P; 441f7d6889bSThierry Reding break; 442f7d6889bSThierry Reding 443f7d6889bSThierry Reding default: 444f7d6889bSThierry Reding return -EINVAL; 445f7d6889bSThierry Reding } 446f7d6889bSThierry Reding 447f7d6889bSThierry Reding return 0; 448f7d6889bSThierry Reding } 449f7d6889bSThierry Reding 450e94236cdSThierry Reding static void tegra_dsi_ganged_enable(struct tegra_dsi *dsi, unsigned int start, 451e94236cdSThierry Reding unsigned int size) 452e94236cdSThierry Reding { 453e94236cdSThierry Reding u32 value; 454e94236cdSThierry Reding 455e94236cdSThierry Reding tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START); 456e94236cdSThierry Reding tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE); 457e94236cdSThierry Reding 458e94236cdSThierry Reding value = DSI_GANGED_MODE_CONTROL_ENABLE; 459e94236cdSThierry Reding tegra_dsi_writel(dsi, value, DSI_GANGED_MODE_CONTROL); 460e94236cdSThierry Reding } 461e94236cdSThierry Reding 462563eff1fSThierry Reding static void tegra_dsi_enable(struct tegra_dsi *dsi) 463dec72739SThierry Reding { 464563eff1fSThierry Reding u32 value; 465dec72739SThierry Reding 466563eff1fSThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 467563eff1fSThierry Reding value |= DSI_POWER_CONTROL_ENABLE; 468563eff1fSThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 469e94236cdSThierry Reding 470e94236cdSThierry Reding if (dsi->slave) 471e94236cdSThierry Reding tegra_dsi_enable(dsi->slave); 472e94236cdSThierry Reding } 473e94236cdSThierry Reding 474e94236cdSThierry Reding static unsigned int tegra_dsi_get_lanes(struct tegra_dsi *dsi) 475e94236cdSThierry Reding { 476e94236cdSThierry Reding if (dsi->master) 477e94236cdSThierry Reding return dsi->master->lanes + dsi->lanes; 478e94236cdSThierry Reding 479e94236cdSThierry Reding if (dsi->slave) 480e94236cdSThierry Reding return dsi->lanes + dsi->slave->lanes; 481e94236cdSThierry Reding 482e94236cdSThierry Reding return dsi->lanes; 483563eff1fSThierry Reding } 484563eff1fSThierry Reding 485563eff1fSThierry Reding static int tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe, 486563eff1fSThierry Reding const struct drm_display_mode *mode) 487563eff1fSThierry Reding { 488563eff1fSThierry Reding unsigned int hact, hsw, hbp, hfp, i, mul, div; 489563eff1fSThierry Reding enum tegra_dsi_format format; 490563eff1fSThierry Reding const u32 *pkt_seq; 491563eff1fSThierry Reding u32 value; 492563eff1fSThierry Reding int err; 493334ae6b5SThierry Reding 49417297a28SThierry Reding if (dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { 49517297a28SThierry Reding DRM_DEBUG_KMS("Non-burst video mode with sync pulses\n"); 49617297a28SThierry Reding pkt_seq = pkt_seq_video_non_burst_sync_pulses; 497337b443dSThierry Reding } else if (dsi->flags & MIPI_DSI_MODE_VIDEO) { 49817297a28SThierry Reding DRM_DEBUG_KMS("Non-burst video mode with sync events\n"); 49917297a28SThierry Reding pkt_seq = pkt_seq_video_non_burst_sync_events; 500337b443dSThierry Reding } else { 501337b443dSThierry Reding DRM_DEBUG_KMS("Command mode\n"); 502337b443dSThierry Reding pkt_seq = pkt_seq_command_mode; 50317297a28SThierry Reding } 50417297a28SThierry Reding 505dec72739SThierry Reding err = tegra_dsi_get_muldiv(dsi->format, &mul, &div); 506dec72739SThierry Reding if (err < 0) 507dec72739SThierry Reding return err; 508dec72739SThierry Reding 509f7d6889bSThierry Reding err = tegra_dsi_get_format(dsi->format, &format); 510f7d6889bSThierry Reding if (err < 0) 511f7d6889bSThierry Reding return err; 512f7d6889bSThierry Reding 513f7d6889bSThierry Reding value = DSI_CONTROL_CHANNEL(0) | DSI_CONTROL_FORMAT(format) | 514dec72739SThierry Reding DSI_CONTROL_LANES(dsi->lanes - 1) | 515563eff1fSThierry Reding DSI_CONTROL_SOURCE(pipe); 516dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_CONTROL); 517dec72739SThierry Reding 518976cebc3SThierry Reding tegra_dsi_writel(dsi, dsi->video_fifo_depth, DSI_MAX_THRESHOLD); 519dec72739SThierry Reding 520563eff1fSThierry Reding value = DSI_HOST_CONTROL_HS; 521dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 522dec72739SThierry Reding 523dec72739SThierry Reding value = tegra_dsi_readl(dsi, DSI_CONTROL); 524563eff1fSThierry Reding 5250c6b1e4bSAlexandre Courbot if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) 526dec72739SThierry Reding value |= DSI_CONTROL_HS_CLK_CTRL; 527563eff1fSThierry Reding 528dec72739SThierry Reding value &= ~DSI_CONTROL_TX_TRIG(3); 529337b443dSThierry Reding 530337b443dSThierry Reding /* enable DCS commands for command mode */ 531337b443dSThierry Reding if (dsi->flags & MIPI_DSI_MODE_VIDEO) 532dec72739SThierry Reding value &= ~DSI_CONTROL_DCS_ENABLE; 533337b443dSThierry Reding else 534337b443dSThierry Reding value |= DSI_CONTROL_DCS_ENABLE; 535337b443dSThierry Reding 536dec72739SThierry Reding value |= DSI_CONTROL_VIDEO_ENABLE; 537dec72739SThierry Reding value &= ~DSI_CONTROL_HOST_ENABLE; 538dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_CONTROL); 539dec72739SThierry Reding 540dec72739SThierry Reding for (i = 0; i < NUM_PKT_SEQ; i++) 541dec72739SThierry Reding tegra_dsi_writel(dsi, pkt_seq[i], DSI_PKT_SEQ_0_LO + i); 542dec72739SThierry Reding 543337b443dSThierry Reding if (dsi->flags & MIPI_DSI_MODE_VIDEO) { 544dec72739SThierry Reding /* horizontal active pixels */ 545dec72739SThierry Reding hact = mode->hdisplay * mul / div; 546dec72739SThierry Reding 547dec72739SThierry Reding /* horizontal sync width */ 548dec72739SThierry Reding hsw = (mode->hsync_end - mode->hsync_start) * mul / div; 549dec72739SThierry Reding hsw -= 10; 550dec72739SThierry Reding 551dec72739SThierry Reding /* horizontal back porch */ 552dec72739SThierry Reding hbp = (mode->htotal - mode->hsync_end) * mul / div; 553dec72739SThierry Reding hbp -= 14; 554dec72739SThierry Reding 555dec72739SThierry Reding /* horizontal front porch */ 556dec72739SThierry Reding hfp = (mode->hsync_start - mode->hdisplay) * mul / div; 557dec72739SThierry Reding hfp -= 8; 558dec72739SThierry Reding 559dec72739SThierry Reding tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1); 560dec72739SThierry Reding tegra_dsi_writel(dsi, hact << 16 | hbp, DSI_PKT_LEN_2_3); 561dec72739SThierry Reding tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5); 562dec72739SThierry Reding tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7); 563dec72739SThierry Reding 564563eff1fSThierry Reding /* set SOL delay (for non-burst mode only) */ 565dec72739SThierry Reding tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY); 566e94236cdSThierry Reding 567e94236cdSThierry Reding /* TODO: implement ganged mode */ 568337b443dSThierry Reding } else { 569337b443dSThierry Reding u16 bytes; 570337b443dSThierry Reding 571e94236cdSThierry Reding if (dsi->master || dsi->slave) { 572e94236cdSThierry Reding /* 573e94236cdSThierry Reding * For ganged mode, assume symmetric left-right mode. 574e94236cdSThierry Reding */ 575e94236cdSThierry Reding bytes = 1 + (mode->hdisplay / 2) * mul / div; 576e94236cdSThierry Reding } else { 577337b443dSThierry Reding /* 1 byte (DCS command) + pixel data */ 578337b443dSThierry Reding bytes = 1 + mode->hdisplay * mul / div; 579e94236cdSThierry Reding } 580337b443dSThierry Reding 581337b443dSThierry Reding tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_0_1); 582337b443dSThierry Reding tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_2_3); 583337b443dSThierry Reding tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_4_5); 584337b443dSThierry Reding tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_6_7); 585337b443dSThierry Reding 586337b443dSThierry Reding value = MIPI_DCS_WRITE_MEMORY_START << 8 | 587337b443dSThierry Reding MIPI_DCS_WRITE_MEMORY_CONTINUE; 588337b443dSThierry Reding tegra_dsi_writel(dsi, value, DSI_DCS_CMDS); 589337b443dSThierry Reding 590e94236cdSThierry Reding /* set SOL delay */ 591e94236cdSThierry Reding if (dsi->master || dsi->slave) { 592e94236cdSThierry Reding unsigned int lanes = tegra_dsi_get_lanes(dsi); 593e94236cdSThierry Reding unsigned long delay, bclk, bclk_ganged; 594e94236cdSThierry Reding 595e94236cdSThierry Reding /* SOL to valid, valid to FIFO and FIFO write delay */ 596e94236cdSThierry Reding delay = 4 + 4 + 2; 597e94236cdSThierry Reding delay = DIV_ROUND_UP(delay * mul, div * lanes); 598e94236cdSThierry Reding /* FIFO read delay */ 599e94236cdSThierry Reding delay = delay + 6; 600e94236cdSThierry Reding 601e94236cdSThierry Reding bclk = DIV_ROUND_UP(mode->htotal * mul, div * lanes); 602e94236cdSThierry Reding bclk_ganged = DIV_ROUND_UP(bclk * lanes / 2, lanes); 603e94236cdSThierry Reding value = bclk - bclk_ganged + delay + 20; 604e94236cdSThierry Reding } else { 605e94236cdSThierry Reding /* TODO: revisit for non-ganged mode */ 606337b443dSThierry Reding value = 8 * mul / div; 607e94236cdSThierry Reding } 608337b443dSThierry Reding 609337b443dSThierry Reding tegra_dsi_writel(dsi, value, DSI_SOL_DELAY); 610337b443dSThierry Reding } 611dec72739SThierry Reding 612e94236cdSThierry Reding if (dsi->slave) { 613e94236cdSThierry Reding err = tegra_dsi_configure(dsi->slave, pipe, mode); 614e94236cdSThierry Reding if (err < 0) 615e94236cdSThierry Reding return err; 616e94236cdSThierry Reding 617e94236cdSThierry Reding /* 618e94236cdSThierry Reding * TODO: Support modes other than symmetrical left-right 619e94236cdSThierry Reding * split. 620e94236cdSThierry Reding */ 621e94236cdSThierry Reding tegra_dsi_ganged_enable(dsi, 0, mode->hdisplay / 2); 622e94236cdSThierry Reding tegra_dsi_ganged_enable(dsi->slave, mode->hdisplay / 2, 623e94236cdSThierry Reding mode->hdisplay / 2); 624e94236cdSThierry Reding } 625e94236cdSThierry Reding 626563eff1fSThierry Reding return 0; 627563eff1fSThierry Reding } 628563eff1fSThierry Reding 629563eff1fSThierry Reding static int tegra_dsi_wait_idle(struct tegra_dsi *dsi, unsigned long timeout) 630563eff1fSThierry Reding { 631563eff1fSThierry Reding u32 value; 632563eff1fSThierry Reding 633563eff1fSThierry Reding timeout = jiffies + msecs_to_jiffies(timeout); 634563eff1fSThierry Reding 635563eff1fSThierry Reding while (time_before(jiffies, timeout)) { 636563eff1fSThierry Reding value = tegra_dsi_readl(dsi, DSI_STATUS); 637563eff1fSThierry Reding if (value & DSI_STATUS_IDLE) 638563eff1fSThierry Reding return 0; 639563eff1fSThierry Reding 640563eff1fSThierry Reding usleep_range(1000, 2000); 641563eff1fSThierry Reding } 642563eff1fSThierry Reding 643563eff1fSThierry Reding return -ETIMEDOUT; 644563eff1fSThierry Reding } 645563eff1fSThierry Reding 646563eff1fSThierry Reding static void tegra_dsi_video_disable(struct tegra_dsi *dsi) 647563eff1fSThierry Reding { 648563eff1fSThierry Reding u32 value; 649563eff1fSThierry Reding 650563eff1fSThierry Reding value = tegra_dsi_readl(dsi, DSI_CONTROL); 651563eff1fSThierry Reding value &= ~DSI_CONTROL_VIDEO_ENABLE; 652563eff1fSThierry Reding tegra_dsi_writel(dsi, value, DSI_CONTROL); 653e94236cdSThierry Reding 654e94236cdSThierry Reding if (dsi->slave) 655e94236cdSThierry Reding tegra_dsi_video_disable(dsi->slave); 656e94236cdSThierry Reding } 657e94236cdSThierry Reding 658e94236cdSThierry Reding static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi) 659e94236cdSThierry Reding { 660e94236cdSThierry Reding tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START); 661e94236cdSThierry Reding tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE); 662e94236cdSThierry Reding tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL); 663563eff1fSThierry Reding } 664563eff1fSThierry Reding 6655b901e78SThierry Reding static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk, 6665b901e78SThierry Reding unsigned int vrefresh) 6675b901e78SThierry Reding { 6685b901e78SThierry Reding unsigned int timeout; 6695b901e78SThierry Reding u32 value; 6705b901e78SThierry Reding 6715b901e78SThierry Reding /* one frame high-speed transmission timeout */ 6725b901e78SThierry Reding timeout = (bclk / vrefresh) / 512; 6735b901e78SThierry Reding value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout); 6745b901e78SThierry Reding tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0); 6755b901e78SThierry Reding 6765b901e78SThierry Reding /* 2 ms peripheral timeout for panel */ 6775b901e78SThierry Reding timeout = 2 * bclk / 512 * 1000; 6785b901e78SThierry Reding value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000); 6795b901e78SThierry Reding tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1); 6805b901e78SThierry Reding 6815b901e78SThierry Reding value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0); 6825b901e78SThierry Reding tegra_dsi_writel(dsi, value, DSI_TO_TALLY); 6835b901e78SThierry Reding 6845b901e78SThierry Reding if (dsi->slave) 6855b901e78SThierry Reding tegra_dsi_set_timeout(dsi->slave, bclk, vrefresh); 6865b901e78SThierry Reding } 6875b901e78SThierry Reding 688563eff1fSThierry Reding static void tegra_dsi_disable(struct tegra_dsi *dsi) 689563eff1fSThierry Reding { 690563eff1fSThierry Reding u32 value; 691563eff1fSThierry Reding 692e94236cdSThierry Reding if (dsi->slave) { 693e94236cdSThierry Reding tegra_dsi_ganged_disable(dsi->slave); 694e94236cdSThierry Reding tegra_dsi_ganged_disable(dsi); 695e94236cdSThierry Reding } 696e94236cdSThierry Reding 697563eff1fSThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 698563eff1fSThierry Reding value &= ~DSI_POWER_CONTROL_ENABLE; 699563eff1fSThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 700563eff1fSThierry Reding 701e94236cdSThierry Reding if (dsi->slave) 702e94236cdSThierry Reding tegra_dsi_disable(dsi->slave); 703e94236cdSThierry Reding 704563eff1fSThierry Reding usleep_range(5000, 10000); 705563eff1fSThierry Reding } 706563eff1fSThierry Reding 70792f0e073SThierry Reding static void tegra_dsi_soft_reset(struct tegra_dsi *dsi) 70892f0e073SThierry Reding { 70992f0e073SThierry Reding u32 value; 71092f0e073SThierry Reding 71192f0e073SThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 71292f0e073SThierry Reding value &= ~DSI_POWER_CONTROL_ENABLE; 71392f0e073SThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 71492f0e073SThierry Reding 71592f0e073SThierry Reding usleep_range(300, 1000); 71692f0e073SThierry Reding 71792f0e073SThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 71892f0e073SThierry Reding value |= DSI_POWER_CONTROL_ENABLE; 71992f0e073SThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 72092f0e073SThierry Reding 72192f0e073SThierry Reding usleep_range(300, 1000); 72292f0e073SThierry Reding 72392f0e073SThierry Reding value = tegra_dsi_readl(dsi, DSI_TRIGGER); 72492f0e073SThierry Reding if (value) 72592f0e073SThierry Reding tegra_dsi_writel(dsi, 0, DSI_TRIGGER); 72692f0e073SThierry Reding 72792f0e073SThierry Reding if (dsi->slave) 72892f0e073SThierry Reding tegra_dsi_soft_reset(dsi->slave); 72992f0e073SThierry Reding } 73092f0e073SThierry Reding 7315b901e78SThierry Reding static void tegra_dsi_connector_dpms(struct drm_connector *connector, int mode) 732dec72739SThierry Reding { 7335b901e78SThierry Reding } 7345b901e78SThierry Reding 7355b901e78SThierry Reding static const struct drm_connector_funcs tegra_dsi_connector_funcs = { 7365b901e78SThierry Reding .dpms = tegra_dsi_connector_dpms, 7375b901e78SThierry Reding .detect = tegra_output_connector_detect, 7385b901e78SThierry Reding .fill_modes = drm_helper_probe_single_connector_modes, 7395b901e78SThierry Reding .destroy = tegra_output_connector_destroy, 740*4aa3df71SThierry Reding .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 7415b901e78SThierry Reding }; 7425b901e78SThierry Reding 7435b901e78SThierry Reding static enum drm_mode_status 7445b901e78SThierry Reding tegra_dsi_connector_mode_valid(struct drm_connector *connector, 7455b901e78SThierry Reding struct drm_display_mode *mode) 7465b901e78SThierry Reding { 7475b901e78SThierry Reding return MODE_OK; 7485b901e78SThierry Reding } 7495b901e78SThierry Reding 7505b901e78SThierry Reding static const struct drm_connector_helper_funcs tegra_dsi_connector_helper_funcs = { 7515b901e78SThierry Reding .get_modes = tegra_output_connector_get_modes, 7525b901e78SThierry Reding .mode_valid = tegra_dsi_connector_mode_valid, 7535b901e78SThierry Reding .best_encoder = tegra_output_connector_best_encoder, 7545b901e78SThierry Reding }; 7555b901e78SThierry Reding 7565b901e78SThierry Reding static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = { 7575b901e78SThierry Reding .destroy = tegra_output_encoder_destroy, 7585b901e78SThierry Reding }; 7595b901e78SThierry Reding 7605b901e78SThierry Reding static void tegra_dsi_encoder_dpms(struct drm_encoder *encoder, int mode) 7615b901e78SThierry Reding { 7625b901e78SThierry Reding } 7635b901e78SThierry Reding 7645b901e78SThierry Reding static bool tegra_dsi_encoder_mode_fixup(struct drm_encoder *encoder, 7655b901e78SThierry Reding const struct drm_display_mode *mode, 7665b901e78SThierry Reding struct drm_display_mode *adjusted) 7675b901e78SThierry Reding { 7685b901e78SThierry Reding struct tegra_output *output = encoder_to_output(encoder); 7695b901e78SThierry Reding struct tegra_dc *dc = to_tegra_dc(encoder->crtc); 7705b901e78SThierry Reding unsigned int mul, div, scdiv, vrefresh, lanes; 771dec72739SThierry Reding struct tegra_dsi *dsi = to_dsi(output); 7725b901e78SThierry Reding unsigned long pclk, bclk, plld; 773dec72739SThierry Reding int err; 774dec72739SThierry Reding 775e94236cdSThierry Reding lanes = tegra_dsi_get_lanes(dsi); 7765b901e78SThierry Reding pclk = mode->clock * 1000; 777e94236cdSThierry Reding 778dec72739SThierry Reding err = tegra_dsi_get_muldiv(dsi->format, &mul, &div); 779dec72739SThierry Reding if (err < 0) 780dec72739SThierry Reding return err; 781dec72739SThierry Reding 782e94236cdSThierry Reding DRM_DEBUG_KMS("mul: %u, div: %u, lanes: %u\n", mul, div, lanes); 783dec72739SThierry Reding vrefresh = drm_mode_vrefresh(mode); 78491eded9bSThierry Reding DRM_DEBUG_KMS("vrefresh: %u\n", vrefresh); 785dec72739SThierry Reding 78691eded9bSThierry Reding /* compute byte clock */ 787e94236cdSThierry Reding bclk = (pclk * mul) / (div * lanes); 78891eded9bSThierry Reding 78991eded9bSThierry Reding /* 79091eded9bSThierry Reding * Compute bit clock and round up to the next MHz. 79191eded9bSThierry Reding */ 792030611ecSThierry Reding plld = DIV_ROUND_UP(bclk * 8, USEC_PER_SEC) * USEC_PER_SEC; 79391eded9bSThierry Reding 79491eded9bSThierry Reding /* 79591eded9bSThierry Reding * We divide the frequency by two here, but we make up for that by 79691eded9bSThierry Reding * setting the shift clock divider (further below) to half of the 79791eded9bSThierry Reding * correct value. 79891eded9bSThierry Reding */ 79991eded9bSThierry Reding plld /= 2; 800dec72739SThierry Reding 801dec72739SThierry Reding /* 80291eded9bSThierry Reding * Derive pixel clock from bit clock using the shift clock divider. 80391eded9bSThierry Reding * Note that this is only half of what we would expect, but we need 80491eded9bSThierry Reding * that to make up for the fact that we divided the bit clock by a 80591eded9bSThierry Reding * factor of two above. 80691eded9bSThierry Reding * 80791eded9bSThierry Reding * It's not clear exactly why this is necessary, but the display is 80891eded9bSThierry Reding * not working properly otherwise. Perhaps the PLLs cannot generate 80991eded9bSThierry Reding * frequencies sufficiently high. 81091eded9bSThierry Reding */ 8115b901e78SThierry Reding scdiv = ((8 * mul) / (div * lanes)) - 2; 81291eded9bSThierry Reding 8135b901e78SThierry Reding err = tegra_dc_setup_clock(dc, dsi->clk_parent, plld, scdiv); 8145b901e78SThierry Reding if (err < 0) { 8155b901e78SThierry Reding dev_err(output->dev, "failed to setup DC clock: %d\n", err); 8165b901e78SThierry Reding return false; 8175b901e78SThierry Reding } 8185b901e78SThierry Reding 8195b901e78SThierry Reding err = clk_set_rate(dsi->clk_parent, plld); 8205b901e78SThierry Reding if (err < 0) { 8215b901e78SThierry Reding dev_err(dsi->dev, "failed to set clock rate to %lu Hz\n", 8225b901e78SThierry Reding plld); 8235b901e78SThierry Reding return false; 8245b901e78SThierry Reding } 8255b901e78SThierry Reding 8263f6b406fSThierry Reding tegra_dsi_set_timeout(dsi, bclk, vrefresh); 827dec72739SThierry Reding 8287e3bc3a9SSean Paul err = tegra_dsi_set_phy_timing(dsi); 8295b901e78SThierry Reding if (err < 0) { 8305b901e78SThierry Reding dev_err(dsi->dev, "failed to setup D-PHY timing: %d\n", err); 8315b901e78SThierry Reding return false; 832dec72739SThierry Reding } 833dec72739SThierry Reding 8345b901e78SThierry Reding return true; 8355b901e78SThierry Reding } 8365b901e78SThierry Reding 8375b901e78SThierry Reding static void tegra_dsi_encoder_prepare(struct drm_encoder *encoder) 838dec72739SThierry Reding { 839dec72739SThierry Reding } 840dec72739SThierry Reding 8415b901e78SThierry Reding static void tegra_dsi_encoder_commit(struct drm_encoder *encoder) 8425b901e78SThierry Reding { 8435b901e78SThierry Reding } 8445b901e78SThierry Reding 8455b901e78SThierry Reding static void tegra_dsi_encoder_mode_set(struct drm_encoder *encoder, 8465b901e78SThierry Reding struct drm_display_mode *mode, 8475b901e78SThierry Reding struct drm_display_mode *adjusted) 8485b901e78SThierry Reding { 8495b901e78SThierry Reding struct tegra_output *output = encoder_to_output(encoder); 8505b901e78SThierry Reding struct tegra_dc *dc = to_tegra_dc(encoder->crtc); 8515b901e78SThierry Reding struct tegra_dsi *dsi = to_dsi(output); 8525b901e78SThierry Reding u32 value; 8535b901e78SThierry Reding int err; 8545b901e78SThierry Reding 8555b901e78SThierry Reding 8565b901e78SThierry Reding err = tegra_dsi_configure(dsi, dc->pipe, mode); 8575b901e78SThierry Reding if (err < 0) { 8585b901e78SThierry Reding dev_err(dsi->dev, "failed to configure DSI: %d\n", err); 8595b901e78SThierry Reding return; 8605b901e78SThierry Reding } 8615b901e78SThierry Reding 8625b901e78SThierry Reding if (output->panel) 8635b901e78SThierry Reding drm_panel_prepare(output->panel); 8645b901e78SThierry Reding 8655b901e78SThierry Reding /* enable display controller */ 8665b901e78SThierry Reding value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 8675b901e78SThierry Reding value |= DSI_ENABLE; 8685b901e78SThierry Reding tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 8695b901e78SThierry Reding 8705b901e78SThierry Reding value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); 8715b901e78SThierry Reding value &= ~DISP_CTRL_MODE_MASK; 8725b901e78SThierry Reding value |= DISP_CTRL_MODE_C_DISPLAY; 8735b901e78SThierry Reding tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); 8745b901e78SThierry Reding 8755b901e78SThierry Reding value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL); 8765b901e78SThierry Reding value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | 8775b901e78SThierry Reding PW4_ENABLE | PM0_ENABLE | PM1_ENABLE; 8785b901e78SThierry Reding tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); 8795b901e78SThierry Reding 8805b901e78SThierry Reding tegra_dc_commit(dc); 8815b901e78SThierry Reding 8825b901e78SThierry Reding /* enable DSI controller */ 8835b901e78SThierry Reding tegra_dsi_enable(dsi); 8845b901e78SThierry Reding 8855b901e78SThierry Reding if (output->panel) 8865b901e78SThierry Reding drm_panel_enable(output->panel); 8875b901e78SThierry Reding 8885b901e78SThierry Reding return; 8895b901e78SThierry Reding } 8905b901e78SThierry Reding 8915b901e78SThierry Reding static void tegra_dsi_encoder_disable(struct drm_encoder *encoder) 8925b901e78SThierry Reding { 8935b901e78SThierry Reding struct tegra_output *output = encoder_to_output(encoder); 8945b901e78SThierry Reding struct tegra_dc *dc = to_tegra_dc(encoder->crtc); 8955b901e78SThierry Reding struct tegra_dsi *dsi = to_dsi(output); 8965b901e78SThierry Reding u32 value; 8975b901e78SThierry Reding int err; 8985b901e78SThierry Reding 8995b901e78SThierry Reding if (output->panel) 9005b901e78SThierry Reding drm_panel_disable(output->panel); 9015b901e78SThierry Reding 9025b901e78SThierry Reding tegra_dsi_video_disable(dsi); 9035b901e78SThierry Reding 9045b901e78SThierry Reding /* 9055b901e78SThierry Reding * The following accesses registers of the display controller, so make 9065b901e78SThierry Reding * sure it's only executed when the output is attached to one. 9075b901e78SThierry Reding */ 9085b901e78SThierry Reding if (dc) { 9095b901e78SThierry Reding value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 9105b901e78SThierry Reding value &= ~DSI_ENABLE; 9115b901e78SThierry Reding tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 9125b901e78SThierry Reding 9135b901e78SThierry Reding tegra_dc_commit(dc); 9145b901e78SThierry Reding } 9155b901e78SThierry Reding 9165b901e78SThierry Reding err = tegra_dsi_wait_idle(dsi, 100); 9175b901e78SThierry Reding if (err < 0) 9185b901e78SThierry Reding dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err); 9195b901e78SThierry Reding 9205b901e78SThierry Reding tegra_dsi_soft_reset(dsi); 9215b901e78SThierry Reding 9225b901e78SThierry Reding if (output->panel) 9235b901e78SThierry Reding drm_panel_unprepare(output->panel); 9245b901e78SThierry Reding 9255b901e78SThierry Reding tegra_dsi_disable(dsi); 9265b901e78SThierry Reding 9275b901e78SThierry Reding return; 9285b901e78SThierry Reding } 9295b901e78SThierry Reding 9305b901e78SThierry Reding static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = { 9315b901e78SThierry Reding .dpms = tegra_dsi_encoder_dpms, 9325b901e78SThierry Reding .mode_fixup = tegra_dsi_encoder_mode_fixup, 9335b901e78SThierry Reding .prepare = tegra_dsi_encoder_prepare, 9345b901e78SThierry Reding .commit = tegra_dsi_encoder_commit, 9355b901e78SThierry Reding .mode_set = tegra_dsi_encoder_mode_set, 9365b901e78SThierry Reding .disable = tegra_dsi_encoder_disable, 937dec72739SThierry Reding }; 938dec72739SThierry Reding 939dec72739SThierry Reding static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) 940dec72739SThierry Reding { 9419c0b4ca1SThierry Reding u32 value; 942dec72739SThierry Reding 943dec72739SThierry Reding value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); 944dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0); 945dec72739SThierry Reding 946dec72739SThierry Reding return 0; 947dec72739SThierry Reding } 948dec72739SThierry Reding 949dec72739SThierry Reding static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi) 950dec72739SThierry Reding { 951183ef288SThierry Reding u32 value; 952dec72739SThierry Reding 953dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0); 954dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1); 955dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2); 956dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3); 957dec72739SThierry Reding tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4); 958dec72739SThierry Reding 959dec72739SThierry Reding /* start calibration */ 960dec72739SThierry Reding tegra_dsi_pad_enable(dsi); 961dec72739SThierry Reding 962dec72739SThierry Reding value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | 963dec72739SThierry Reding DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | 964dec72739SThierry Reding DSI_PAD_OUT_CLK(0x0); 965dec72739SThierry Reding tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); 966dec72739SThierry Reding 967dec72739SThierry Reding return tegra_mipi_calibrate(dsi->mipi); 968dec72739SThierry Reding } 969dec72739SThierry Reding 970dec72739SThierry Reding static int tegra_dsi_init(struct host1x_client *client) 971dec72739SThierry Reding { 9729910f5c4SThierry Reding struct drm_device *drm = dev_get_drvdata(client->parent); 973dec72739SThierry Reding struct tegra_dsi *dsi = host1x_client_to_dsi(client); 974dec72739SThierry Reding int err; 975dec72739SThierry Reding 976201106d8SThierry Reding reset_control_deassert(dsi->rst); 977201106d8SThierry Reding 978201106d8SThierry Reding err = tegra_dsi_pad_calibrate(dsi); 979201106d8SThierry Reding if (err < 0) { 980201106d8SThierry Reding dev_err(dsi->dev, "MIPI calibration failed: %d\n", err); 981201106d8SThierry Reding goto reset; 982201106d8SThierry Reding } 983201106d8SThierry Reding 984e94236cdSThierry Reding /* Gangsters must not register their own outputs. */ 985e94236cdSThierry Reding if (!dsi->master) { 986dec72739SThierry Reding dsi->output.dev = client->dev; 987dec72739SThierry Reding 9885b901e78SThierry Reding drm_connector_init(drm, &dsi->output.connector, 9895b901e78SThierry Reding &tegra_dsi_connector_funcs, 9905b901e78SThierry Reding DRM_MODE_CONNECTOR_DSI); 9915b901e78SThierry Reding drm_connector_helper_add(&dsi->output.connector, 9925b901e78SThierry Reding &tegra_dsi_connector_helper_funcs); 9935b901e78SThierry Reding dsi->output.connector.dpms = DRM_MODE_DPMS_OFF; 9945b901e78SThierry Reding 9955b901e78SThierry Reding drm_encoder_init(drm, &dsi->output.encoder, 9965b901e78SThierry Reding &tegra_dsi_encoder_funcs, 9975b901e78SThierry Reding DRM_MODE_ENCODER_DSI); 9985b901e78SThierry Reding drm_encoder_helper_add(&dsi->output.encoder, 9995b901e78SThierry Reding &tegra_dsi_encoder_helper_funcs); 10005b901e78SThierry Reding 10015b901e78SThierry Reding drm_mode_connector_attach_encoder(&dsi->output.connector, 10025b901e78SThierry Reding &dsi->output.encoder); 10035b901e78SThierry Reding drm_connector_register(&dsi->output.connector); 10045b901e78SThierry Reding 1005ea130b24SThierry Reding err = tegra_output_init(drm, &dsi->output); 1006ea130b24SThierry Reding if (err < 0) { 1007ea130b24SThierry Reding dev_err(client->dev, 1008ea130b24SThierry Reding "failed to initialize output: %d\n", 1009ea130b24SThierry Reding err); 1010ea130b24SThierry Reding goto reset; 1011ea130b24SThierry Reding } 1012ea130b24SThierry Reding 10135b901e78SThierry Reding dsi->output.encoder.possible_crtcs = 0x3; 1014e94236cdSThierry Reding } 1015dec72739SThierry Reding 1016dec72739SThierry Reding if (IS_ENABLED(CONFIG_DEBUG_FS)) { 10179910f5c4SThierry Reding err = tegra_dsi_debugfs_init(dsi, drm->primary); 1018dec72739SThierry Reding if (err < 0) 1019dec72739SThierry Reding dev_err(dsi->dev, "debugfs setup failed: %d\n", err); 1020dec72739SThierry Reding } 1021dec72739SThierry Reding 1022dec72739SThierry Reding return 0; 1023201106d8SThierry Reding 1024201106d8SThierry Reding reset: 1025201106d8SThierry Reding reset_control_assert(dsi->rst); 1026201106d8SThierry Reding return err; 1027dec72739SThierry Reding } 1028dec72739SThierry Reding 1029dec72739SThierry Reding static int tegra_dsi_exit(struct host1x_client *client) 1030dec72739SThierry Reding { 1031dec72739SThierry Reding struct tegra_dsi *dsi = host1x_client_to_dsi(client); 1032dec72739SThierry Reding 10335b901e78SThierry Reding tegra_output_exit(&dsi->output); 10345b901e78SThierry Reding 10354009c224SThierry Reding if (IS_ENABLED(CONFIG_DEBUG_FS)) 10364009c224SThierry Reding tegra_dsi_debugfs_exit(dsi); 1037dec72739SThierry Reding 1038201106d8SThierry Reding reset_control_assert(dsi->rst); 1039201106d8SThierry Reding 1040dec72739SThierry Reding return 0; 1041dec72739SThierry Reding } 1042dec72739SThierry Reding 1043dec72739SThierry Reding static const struct host1x_client_ops dsi_client_ops = { 1044dec72739SThierry Reding .init = tegra_dsi_init, 1045dec72739SThierry Reding .exit = tegra_dsi_exit, 1046dec72739SThierry Reding }; 1047dec72739SThierry Reding 1048dec72739SThierry Reding static int tegra_dsi_setup_clocks(struct tegra_dsi *dsi) 1049dec72739SThierry Reding { 1050dec72739SThierry Reding struct clk *parent; 1051dec72739SThierry Reding int err; 1052dec72739SThierry Reding 1053dec72739SThierry Reding parent = clk_get_parent(dsi->clk); 1054dec72739SThierry Reding if (!parent) 1055dec72739SThierry Reding return -EINVAL; 1056dec72739SThierry Reding 1057dec72739SThierry Reding err = clk_set_parent(parent, dsi->clk_parent); 1058dec72739SThierry Reding if (err < 0) 1059dec72739SThierry Reding return err; 1060dec72739SThierry Reding 1061dec72739SThierry Reding return 0; 1062dec72739SThierry Reding } 1063dec72739SThierry Reding 10640fffdf6cSThierry Reding static const char * const error_report[16] = { 10650fffdf6cSThierry Reding "SoT Error", 10660fffdf6cSThierry Reding "SoT Sync Error", 10670fffdf6cSThierry Reding "EoT Sync Error", 10680fffdf6cSThierry Reding "Escape Mode Entry Command Error", 10690fffdf6cSThierry Reding "Low-Power Transmit Sync Error", 10700fffdf6cSThierry Reding "Peripheral Timeout Error", 10710fffdf6cSThierry Reding "False Control Error", 10720fffdf6cSThierry Reding "Contention Detected", 10730fffdf6cSThierry Reding "ECC Error, single-bit", 10740fffdf6cSThierry Reding "ECC Error, multi-bit", 10750fffdf6cSThierry Reding "Checksum Error", 10760fffdf6cSThierry Reding "DSI Data Type Not Recognized", 10770fffdf6cSThierry Reding "DSI VC ID Invalid", 10780fffdf6cSThierry Reding "Invalid Transmission Length", 10790fffdf6cSThierry Reding "Reserved", 10800fffdf6cSThierry Reding "DSI Protocol Violation", 10810fffdf6cSThierry Reding }; 10820fffdf6cSThierry Reding 10830fffdf6cSThierry Reding static ssize_t tegra_dsi_read_response(struct tegra_dsi *dsi, 10840fffdf6cSThierry Reding const struct mipi_dsi_msg *msg, 10850fffdf6cSThierry Reding size_t count) 10860fffdf6cSThierry Reding { 10870fffdf6cSThierry Reding u8 *rx = msg->rx_buf; 10880fffdf6cSThierry Reding unsigned int i, j, k; 10890fffdf6cSThierry Reding size_t size = 0; 10900fffdf6cSThierry Reding u16 errors; 10910fffdf6cSThierry Reding u32 value; 10920fffdf6cSThierry Reding 10930fffdf6cSThierry Reding /* read and parse packet header */ 10940fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_RD_DATA); 10950fffdf6cSThierry Reding 10960fffdf6cSThierry Reding switch (value & 0x3f) { 10970fffdf6cSThierry Reding case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT: 10980fffdf6cSThierry Reding errors = (value >> 8) & 0xffff; 10990fffdf6cSThierry Reding dev_dbg(dsi->dev, "Acknowledge and error report: %04x\n", 11000fffdf6cSThierry Reding errors); 11010fffdf6cSThierry Reding for (i = 0; i < ARRAY_SIZE(error_report); i++) 11020fffdf6cSThierry Reding if (errors & BIT(i)) 11030fffdf6cSThierry Reding dev_dbg(dsi->dev, " %2u: %s\n", i, 11040fffdf6cSThierry Reding error_report[i]); 11050fffdf6cSThierry Reding break; 11060fffdf6cSThierry Reding 11070fffdf6cSThierry Reding case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: 11080fffdf6cSThierry Reding rx[0] = (value >> 8) & 0xff; 11090fffdf6cSThierry Reding size = 1; 11100fffdf6cSThierry Reding break; 11110fffdf6cSThierry Reding 11120fffdf6cSThierry Reding case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: 11130fffdf6cSThierry Reding rx[0] = (value >> 8) & 0xff; 11140fffdf6cSThierry Reding rx[1] = (value >> 16) & 0xff; 11150fffdf6cSThierry Reding size = 2; 11160fffdf6cSThierry Reding break; 11170fffdf6cSThierry Reding 11180fffdf6cSThierry Reding case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE: 11190fffdf6cSThierry Reding size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff); 11200fffdf6cSThierry Reding break; 11210fffdf6cSThierry Reding 11220fffdf6cSThierry Reding case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE: 11230fffdf6cSThierry Reding size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff); 11240fffdf6cSThierry Reding break; 11250fffdf6cSThierry Reding 11260fffdf6cSThierry Reding default: 11270fffdf6cSThierry Reding dev_err(dsi->dev, "unhandled response type: %02x\n", 11280fffdf6cSThierry Reding value & 0x3f); 11290fffdf6cSThierry Reding return -EPROTO; 11300fffdf6cSThierry Reding } 11310fffdf6cSThierry Reding 11320fffdf6cSThierry Reding size = min(size, msg->rx_len); 11330fffdf6cSThierry Reding 11340fffdf6cSThierry Reding if (msg->rx_buf && size > 0) { 11350fffdf6cSThierry Reding for (i = 0, j = 0; i < count - 1; i++, j += 4) { 11360fffdf6cSThierry Reding u8 *rx = msg->rx_buf + j; 11370fffdf6cSThierry Reding 11380fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_RD_DATA); 11390fffdf6cSThierry Reding 11400fffdf6cSThierry Reding for (k = 0; k < 4 && (j + k) < msg->rx_len; k++) 11410fffdf6cSThierry Reding rx[j + k] = (value >> (k << 3)) & 0xff; 11420fffdf6cSThierry Reding } 11430fffdf6cSThierry Reding } 11440fffdf6cSThierry Reding 11450fffdf6cSThierry Reding return size; 11460fffdf6cSThierry Reding } 11470fffdf6cSThierry Reding 11480fffdf6cSThierry Reding static int tegra_dsi_transmit(struct tegra_dsi *dsi, unsigned long timeout) 11490fffdf6cSThierry Reding { 11500fffdf6cSThierry Reding tegra_dsi_writel(dsi, DSI_TRIGGER_HOST, DSI_TRIGGER); 11510fffdf6cSThierry Reding 11520fffdf6cSThierry Reding timeout = jiffies + msecs_to_jiffies(timeout); 11530fffdf6cSThierry Reding 11540fffdf6cSThierry Reding while (time_before(jiffies, timeout)) { 11550fffdf6cSThierry Reding u32 value = tegra_dsi_readl(dsi, DSI_TRIGGER); 11560fffdf6cSThierry Reding if ((value & DSI_TRIGGER_HOST) == 0) 11570fffdf6cSThierry Reding return 0; 11580fffdf6cSThierry Reding 11590fffdf6cSThierry Reding usleep_range(1000, 2000); 11600fffdf6cSThierry Reding } 11610fffdf6cSThierry Reding 11620fffdf6cSThierry Reding DRM_DEBUG_KMS("timeout waiting for transmission to complete\n"); 11630fffdf6cSThierry Reding return -ETIMEDOUT; 11640fffdf6cSThierry Reding } 11650fffdf6cSThierry Reding 11660fffdf6cSThierry Reding static int tegra_dsi_wait_for_response(struct tegra_dsi *dsi, 11670fffdf6cSThierry Reding unsigned long timeout) 11680fffdf6cSThierry Reding { 11690fffdf6cSThierry Reding timeout = jiffies + msecs_to_jiffies(250); 11700fffdf6cSThierry Reding 11710fffdf6cSThierry Reding while (time_before(jiffies, timeout)) { 11720fffdf6cSThierry Reding u32 value = tegra_dsi_readl(dsi, DSI_STATUS); 11730fffdf6cSThierry Reding u8 count = value & 0x1f; 11740fffdf6cSThierry Reding 11750fffdf6cSThierry Reding if (count > 0) 11760fffdf6cSThierry Reding return count; 11770fffdf6cSThierry Reding 11780fffdf6cSThierry Reding usleep_range(1000, 2000); 11790fffdf6cSThierry Reding } 11800fffdf6cSThierry Reding 11810fffdf6cSThierry Reding DRM_DEBUG_KMS("peripheral returned no data\n"); 11820fffdf6cSThierry Reding return -ETIMEDOUT; 11830fffdf6cSThierry Reding } 11840fffdf6cSThierry Reding 11850fffdf6cSThierry Reding static void tegra_dsi_writesl(struct tegra_dsi *dsi, unsigned long offset, 11860fffdf6cSThierry Reding const void *buffer, size_t size) 11870fffdf6cSThierry Reding { 11880fffdf6cSThierry Reding const u8 *buf = buffer; 11890fffdf6cSThierry Reding size_t i, j; 11900fffdf6cSThierry Reding u32 value; 11910fffdf6cSThierry Reding 11920fffdf6cSThierry Reding for (j = 0; j < size; j += 4) { 11930fffdf6cSThierry Reding value = 0; 11940fffdf6cSThierry Reding 11950fffdf6cSThierry Reding for (i = 0; i < 4 && j + i < size; i++) 11960fffdf6cSThierry Reding value |= buf[j + i] << (i << 3); 11970fffdf6cSThierry Reding 11980fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_WR_DATA); 11990fffdf6cSThierry Reding } 12000fffdf6cSThierry Reding } 12010fffdf6cSThierry Reding 12020fffdf6cSThierry Reding static ssize_t tegra_dsi_host_transfer(struct mipi_dsi_host *host, 12030fffdf6cSThierry Reding const struct mipi_dsi_msg *msg) 12040fffdf6cSThierry Reding { 12050fffdf6cSThierry Reding struct tegra_dsi *dsi = host_to_tegra(host); 12060fffdf6cSThierry Reding struct mipi_dsi_packet packet; 12070fffdf6cSThierry Reding const u8 *header; 12080fffdf6cSThierry Reding size_t count; 12090fffdf6cSThierry Reding ssize_t err; 12100fffdf6cSThierry Reding u32 value; 12110fffdf6cSThierry Reding 12120fffdf6cSThierry Reding err = mipi_dsi_create_packet(&packet, msg); 12130fffdf6cSThierry Reding if (err < 0) 12140fffdf6cSThierry Reding return err; 12150fffdf6cSThierry Reding 12160fffdf6cSThierry Reding header = packet.header; 12170fffdf6cSThierry Reding 12180fffdf6cSThierry Reding /* maximum FIFO depth is 1920 words */ 12190fffdf6cSThierry Reding if (packet.size > dsi->video_fifo_depth * 4) 12200fffdf6cSThierry Reding return -ENOSPC; 12210fffdf6cSThierry Reding 12220fffdf6cSThierry Reding /* reset underflow/overflow flags */ 12230fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_STATUS); 12240fffdf6cSThierry Reding if (value & (DSI_STATUS_UNDERFLOW | DSI_STATUS_OVERFLOW)) { 12250fffdf6cSThierry Reding value = DSI_HOST_CONTROL_FIFO_RESET; 12260fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 12270fffdf6cSThierry Reding usleep_range(10, 20); 12280fffdf6cSThierry Reding } 12290fffdf6cSThierry Reding 12300fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 12310fffdf6cSThierry Reding value |= DSI_POWER_CONTROL_ENABLE; 12320fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); 12330fffdf6cSThierry Reding 12340fffdf6cSThierry Reding usleep_range(5000, 10000); 12350fffdf6cSThierry Reding 12360fffdf6cSThierry Reding value = DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | 12370fffdf6cSThierry Reding DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC; 12380fffdf6cSThierry Reding 12390fffdf6cSThierry Reding if ((msg->flags & MIPI_DSI_MSG_USE_LPM) == 0) 12400fffdf6cSThierry Reding value |= DSI_HOST_CONTROL_HS; 12410fffdf6cSThierry Reding 12420fffdf6cSThierry Reding /* 12430fffdf6cSThierry Reding * The host FIFO has a maximum of 64 words, so larger transmissions 12440fffdf6cSThierry Reding * need to use the video FIFO. 12450fffdf6cSThierry Reding */ 12460fffdf6cSThierry Reding if (packet.size > dsi->host_fifo_depth * 4) 12470fffdf6cSThierry Reding value |= DSI_HOST_CONTROL_FIFO_SEL; 12480fffdf6cSThierry Reding 12490fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 12500fffdf6cSThierry Reding 12510fffdf6cSThierry Reding /* 12520fffdf6cSThierry Reding * For reads and messages with explicitly requested ACK, generate a 12530fffdf6cSThierry Reding * BTA sequence after the transmission of the packet. 12540fffdf6cSThierry Reding */ 12550fffdf6cSThierry Reding if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) || 12560fffdf6cSThierry Reding (msg->rx_buf && msg->rx_len > 0)) { 12570fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL); 12580fffdf6cSThierry Reding value |= DSI_HOST_CONTROL_PKT_BTA; 12590fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 12600fffdf6cSThierry Reding } 12610fffdf6cSThierry Reding 12620fffdf6cSThierry Reding value = DSI_CONTROL_LANES(0) | DSI_CONTROL_HOST_ENABLE; 12630fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_CONTROL); 12640fffdf6cSThierry Reding 12650fffdf6cSThierry Reding /* write packet header, ECC is generated by hardware */ 12660fffdf6cSThierry Reding value = header[2] << 16 | header[1] << 8 | header[0]; 12670fffdf6cSThierry Reding tegra_dsi_writel(dsi, value, DSI_WR_DATA); 12680fffdf6cSThierry Reding 12690fffdf6cSThierry Reding /* write payload (if any) */ 12700fffdf6cSThierry Reding if (packet.payload_length > 0) 12710fffdf6cSThierry Reding tegra_dsi_writesl(dsi, DSI_WR_DATA, packet.payload, 12720fffdf6cSThierry Reding packet.payload_length); 12730fffdf6cSThierry Reding 12740fffdf6cSThierry Reding err = tegra_dsi_transmit(dsi, 250); 12750fffdf6cSThierry Reding if (err < 0) 12760fffdf6cSThierry Reding return err; 12770fffdf6cSThierry Reding 12780fffdf6cSThierry Reding if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) || 12790fffdf6cSThierry Reding (msg->rx_buf && msg->rx_len > 0)) { 12800fffdf6cSThierry Reding err = tegra_dsi_wait_for_response(dsi, 250); 12810fffdf6cSThierry Reding if (err < 0) 12820fffdf6cSThierry Reding return err; 12830fffdf6cSThierry Reding 12840fffdf6cSThierry Reding count = err; 12850fffdf6cSThierry Reding 12860fffdf6cSThierry Reding value = tegra_dsi_readl(dsi, DSI_RD_DATA); 12870fffdf6cSThierry Reding switch (value) { 12880fffdf6cSThierry Reding case 0x84: 12890fffdf6cSThierry Reding /* 12900fffdf6cSThierry Reding dev_dbg(dsi->dev, "ACK\n"); 12910fffdf6cSThierry Reding */ 12920fffdf6cSThierry Reding break; 12930fffdf6cSThierry Reding 12940fffdf6cSThierry Reding case 0x87: 12950fffdf6cSThierry Reding /* 12960fffdf6cSThierry Reding dev_dbg(dsi->dev, "ESCAPE\n"); 12970fffdf6cSThierry Reding */ 12980fffdf6cSThierry Reding break; 12990fffdf6cSThierry Reding 13000fffdf6cSThierry Reding default: 13010fffdf6cSThierry Reding dev_err(dsi->dev, "unknown status: %08x\n", value); 13020fffdf6cSThierry Reding break; 13030fffdf6cSThierry Reding } 13040fffdf6cSThierry Reding 13050fffdf6cSThierry Reding if (count > 1) { 13060fffdf6cSThierry Reding err = tegra_dsi_read_response(dsi, msg, count); 13070fffdf6cSThierry Reding if (err < 0) 13080fffdf6cSThierry Reding dev_err(dsi->dev, 13090fffdf6cSThierry Reding "failed to parse response: %zd\n", 13100fffdf6cSThierry Reding err); 13110fffdf6cSThierry Reding else { 13120fffdf6cSThierry Reding /* 13130fffdf6cSThierry Reding * For read commands, return the number of 13140fffdf6cSThierry Reding * bytes returned by the peripheral. 13150fffdf6cSThierry Reding */ 13160fffdf6cSThierry Reding count = err; 13170fffdf6cSThierry Reding } 13180fffdf6cSThierry Reding } 13190fffdf6cSThierry Reding } else { 13200fffdf6cSThierry Reding /* 13210fffdf6cSThierry Reding * For write commands, we have transmitted the 4-byte header 13220fffdf6cSThierry Reding * plus the variable-length payload. 13230fffdf6cSThierry Reding */ 13240fffdf6cSThierry Reding count = 4 + packet.payload_length; 13250fffdf6cSThierry Reding } 13260fffdf6cSThierry Reding 13270fffdf6cSThierry Reding return count; 13280fffdf6cSThierry Reding } 13290fffdf6cSThierry Reding 1330e94236cdSThierry Reding static int tegra_dsi_ganged_setup(struct tegra_dsi *dsi) 1331e94236cdSThierry Reding { 1332e94236cdSThierry Reding struct clk *parent; 1333e94236cdSThierry Reding int err; 1334e94236cdSThierry Reding 1335e94236cdSThierry Reding /* make sure both DSI controllers share the same PLL */ 1336e94236cdSThierry Reding parent = clk_get_parent(dsi->slave->clk); 1337e94236cdSThierry Reding if (!parent) 1338e94236cdSThierry Reding return -EINVAL; 1339e94236cdSThierry Reding 1340e94236cdSThierry Reding err = clk_set_parent(parent, dsi->clk_parent); 1341e94236cdSThierry Reding if (err < 0) 1342e94236cdSThierry Reding return err; 1343e94236cdSThierry Reding 1344e94236cdSThierry Reding return 0; 1345e94236cdSThierry Reding } 1346e94236cdSThierry Reding 1347dec72739SThierry Reding static int tegra_dsi_host_attach(struct mipi_dsi_host *host, 1348dec72739SThierry Reding struct mipi_dsi_device *device) 1349dec72739SThierry Reding { 1350dec72739SThierry Reding struct tegra_dsi *dsi = host_to_tegra(host); 1351dec72739SThierry Reding 135217297a28SThierry Reding dsi->flags = device->mode_flags; 1353dec72739SThierry Reding dsi->format = device->format; 1354dec72739SThierry Reding dsi->lanes = device->lanes; 1355dec72739SThierry Reding 1356e94236cdSThierry Reding if (dsi->slave) { 1357e94236cdSThierry Reding int err; 1358e94236cdSThierry Reding 1359e94236cdSThierry Reding dev_dbg(dsi->dev, "attaching dual-channel device %s\n", 1360e94236cdSThierry Reding dev_name(&device->dev)); 1361e94236cdSThierry Reding 1362e94236cdSThierry Reding err = tegra_dsi_ganged_setup(dsi); 1363e94236cdSThierry Reding if (err < 0) { 1364e94236cdSThierry Reding dev_err(dsi->dev, "failed to set up ganged mode: %d\n", 1365e94236cdSThierry Reding err); 1366e94236cdSThierry Reding return err; 1367e94236cdSThierry Reding } 1368e94236cdSThierry Reding } 1369e94236cdSThierry Reding 1370e94236cdSThierry Reding /* 1371e94236cdSThierry Reding * Slaves don't have a panel associated with them, so they provide 1372e94236cdSThierry Reding * merely the second channel. 1373e94236cdSThierry Reding */ 1374e94236cdSThierry Reding if (!dsi->master) { 1375e94236cdSThierry Reding struct tegra_output *output = &dsi->output; 1376e94236cdSThierry Reding 1377dec72739SThierry Reding output->panel = of_drm_find_panel(device->dev.of_node); 1378e94236cdSThierry Reding if (output->panel && output->connector.dev) { 1379e94236cdSThierry Reding drm_panel_attach(output->panel, &output->connector); 1380dec72739SThierry Reding drm_helper_hpd_irq_event(output->connector.dev); 1381dec72739SThierry Reding } 1382e94236cdSThierry Reding } 1383dec72739SThierry Reding 1384dec72739SThierry Reding return 0; 1385dec72739SThierry Reding } 1386dec72739SThierry Reding 1387dec72739SThierry Reding static int tegra_dsi_host_detach(struct mipi_dsi_host *host, 1388dec72739SThierry Reding struct mipi_dsi_device *device) 1389dec72739SThierry Reding { 1390dec72739SThierry Reding struct tegra_dsi *dsi = host_to_tegra(host); 1391dec72739SThierry Reding struct tegra_output *output = &dsi->output; 1392dec72739SThierry Reding 1393dec72739SThierry Reding if (output->panel && &device->dev == output->panel->dev) { 1394ba3df979SThierry Reding output->panel = NULL; 1395ba3df979SThierry Reding 1396dec72739SThierry Reding if (output->connector.dev) 1397dec72739SThierry Reding drm_helper_hpd_irq_event(output->connector.dev); 1398dec72739SThierry Reding } 1399dec72739SThierry Reding 1400dec72739SThierry Reding return 0; 1401dec72739SThierry Reding } 1402dec72739SThierry Reding 1403dec72739SThierry Reding static const struct mipi_dsi_host_ops tegra_dsi_host_ops = { 1404dec72739SThierry Reding .attach = tegra_dsi_host_attach, 1405dec72739SThierry Reding .detach = tegra_dsi_host_detach, 14060fffdf6cSThierry Reding .transfer = tegra_dsi_host_transfer, 1407dec72739SThierry Reding }; 1408dec72739SThierry Reding 1409e94236cdSThierry Reding static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi) 1410e94236cdSThierry Reding { 1411e94236cdSThierry Reding struct device_node *np; 1412e94236cdSThierry Reding 1413e94236cdSThierry Reding np = of_parse_phandle(dsi->dev->of_node, "nvidia,ganged-mode", 0); 1414e94236cdSThierry Reding if (np) { 1415e94236cdSThierry Reding struct platform_device *gangster = of_find_device_by_node(np); 1416e94236cdSThierry Reding 1417e94236cdSThierry Reding dsi->slave = platform_get_drvdata(gangster); 1418e94236cdSThierry Reding of_node_put(np); 1419e94236cdSThierry Reding 1420e94236cdSThierry Reding if (!dsi->slave) 1421e94236cdSThierry Reding return -EPROBE_DEFER; 1422e94236cdSThierry Reding 1423e94236cdSThierry Reding dsi->slave->master = dsi; 1424e94236cdSThierry Reding } 1425e94236cdSThierry Reding 1426e94236cdSThierry Reding return 0; 1427e94236cdSThierry Reding } 1428e94236cdSThierry Reding 1429dec72739SThierry Reding static int tegra_dsi_probe(struct platform_device *pdev) 1430dec72739SThierry Reding { 1431dec72739SThierry Reding struct tegra_dsi *dsi; 1432dec72739SThierry Reding struct resource *regs; 1433dec72739SThierry Reding int err; 1434dec72739SThierry Reding 1435dec72739SThierry Reding dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); 1436dec72739SThierry Reding if (!dsi) 1437dec72739SThierry Reding return -ENOMEM; 1438dec72739SThierry Reding 1439dec72739SThierry Reding dsi->output.dev = dsi->dev = &pdev->dev; 1440976cebc3SThierry Reding dsi->video_fifo_depth = 1920; 1441976cebc3SThierry Reding dsi->host_fifo_depth = 64; 1442dec72739SThierry Reding 1443e94236cdSThierry Reding err = tegra_dsi_ganged_probe(dsi); 1444e94236cdSThierry Reding if (err < 0) 1445e94236cdSThierry Reding return err; 1446e94236cdSThierry Reding 1447dec72739SThierry Reding err = tegra_output_probe(&dsi->output); 1448dec72739SThierry Reding if (err < 0) 1449dec72739SThierry Reding return err; 1450dec72739SThierry Reding 1451ba3df979SThierry Reding dsi->output.connector.polled = DRM_CONNECTOR_POLL_HPD; 1452ba3df979SThierry Reding 1453dec72739SThierry Reding /* 1454dec72739SThierry Reding * Assume these values by default. When a DSI peripheral driver 1455dec72739SThierry Reding * attaches to the DSI host, the parameters will be taken from 1456dec72739SThierry Reding * the attached device. 1457dec72739SThierry Reding */ 145817297a28SThierry Reding dsi->flags = MIPI_DSI_MODE_VIDEO; 1459dec72739SThierry Reding dsi->format = MIPI_DSI_FMT_RGB888; 1460dec72739SThierry Reding dsi->lanes = 4; 1461dec72739SThierry Reding 1462dec72739SThierry Reding dsi->rst = devm_reset_control_get(&pdev->dev, "dsi"); 1463dec72739SThierry Reding if (IS_ERR(dsi->rst)) 1464dec72739SThierry Reding return PTR_ERR(dsi->rst); 1465dec72739SThierry Reding 1466dec72739SThierry Reding dsi->clk = devm_clk_get(&pdev->dev, NULL); 1467dec72739SThierry Reding if (IS_ERR(dsi->clk)) { 1468dec72739SThierry Reding dev_err(&pdev->dev, "cannot get DSI clock\n"); 1469d2d0a9d2SThierry Reding err = PTR_ERR(dsi->clk); 1470d2d0a9d2SThierry Reding goto reset; 1471dec72739SThierry Reding } 1472dec72739SThierry Reding 1473dec72739SThierry Reding err = clk_prepare_enable(dsi->clk); 1474dec72739SThierry Reding if (err < 0) { 1475dec72739SThierry Reding dev_err(&pdev->dev, "cannot enable DSI clock\n"); 1476d2d0a9d2SThierry Reding goto reset; 1477dec72739SThierry Reding } 1478dec72739SThierry Reding 1479dec72739SThierry Reding dsi->clk_lp = devm_clk_get(&pdev->dev, "lp"); 1480dec72739SThierry Reding if (IS_ERR(dsi->clk_lp)) { 1481dec72739SThierry Reding dev_err(&pdev->dev, "cannot get low-power clock\n"); 1482d2d0a9d2SThierry Reding err = PTR_ERR(dsi->clk_lp); 1483d2d0a9d2SThierry Reding goto disable_clk; 1484dec72739SThierry Reding } 1485dec72739SThierry Reding 1486dec72739SThierry Reding err = clk_prepare_enable(dsi->clk_lp); 1487dec72739SThierry Reding if (err < 0) { 1488dec72739SThierry Reding dev_err(&pdev->dev, "cannot enable low-power clock\n"); 1489d2d0a9d2SThierry Reding goto disable_clk; 1490dec72739SThierry Reding } 1491dec72739SThierry Reding 1492dec72739SThierry Reding dsi->clk_parent = devm_clk_get(&pdev->dev, "parent"); 1493dec72739SThierry Reding if (IS_ERR(dsi->clk_parent)) { 1494dec72739SThierry Reding dev_err(&pdev->dev, "cannot get parent clock\n"); 1495d2d0a9d2SThierry Reding err = PTR_ERR(dsi->clk_parent); 1496d2d0a9d2SThierry Reding goto disable_clk_lp; 1497dec72739SThierry Reding } 1498dec72739SThierry Reding 14993b077afbSThierry Reding dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi"); 15003b077afbSThierry Reding if (IS_ERR(dsi->vdd)) { 15013b077afbSThierry Reding dev_err(&pdev->dev, "cannot get VDD supply\n"); 1502d2d0a9d2SThierry Reding err = PTR_ERR(dsi->vdd); 1503d2d0a9d2SThierry Reding goto disable_clk_lp; 15043b077afbSThierry Reding } 15053b077afbSThierry Reding 15063b077afbSThierry Reding err = regulator_enable(dsi->vdd); 15073b077afbSThierry Reding if (err < 0) { 15083b077afbSThierry Reding dev_err(&pdev->dev, "cannot enable VDD supply\n"); 1509d2d0a9d2SThierry Reding goto disable_clk_lp; 15103b077afbSThierry Reding } 15113b077afbSThierry Reding 1512dec72739SThierry Reding err = tegra_dsi_setup_clocks(dsi); 1513dec72739SThierry Reding if (err < 0) { 1514dec72739SThierry Reding dev_err(&pdev->dev, "cannot setup clocks\n"); 1515d2d0a9d2SThierry Reding goto disable_vdd; 1516dec72739SThierry Reding } 1517dec72739SThierry Reding 1518dec72739SThierry Reding regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1519dec72739SThierry Reding dsi->regs = devm_ioremap_resource(&pdev->dev, regs); 1520d2d0a9d2SThierry Reding if (IS_ERR(dsi->regs)) { 1521d2d0a9d2SThierry Reding err = PTR_ERR(dsi->regs); 1522d2d0a9d2SThierry Reding goto disable_vdd; 1523d2d0a9d2SThierry Reding } 1524dec72739SThierry Reding 1525dec72739SThierry Reding dsi->mipi = tegra_mipi_request(&pdev->dev); 1526d2d0a9d2SThierry Reding if (IS_ERR(dsi->mipi)) { 1527d2d0a9d2SThierry Reding err = PTR_ERR(dsi->mipi); 1528d2d0a9d2SThierry Reding goto disable_vdd; 1529d2d0a9d2SThierry Reding } 1530dec72739SThierry Reding 1531dec72739SThierry Reding dsi->host.ops = &tegra_dsi_host_ops; 1532dec72739SThierry Reding dsi->host.dev = &pdev->dev; 1533dec72739SThierry Reding 1534dec72739SThierry Reding err = mipi_dsi_host_register(&dsi->host); 1535dec72739SThierry Reding if (err < 0) { 1536dec72739SThierry Reding dev_err(&pdev->dev, "failed to register DSI host: %d\n", err); 1537d2d0a9d2SThierry Reding goto mipi_free; 1538dec72739SThierry Reding } 1539dec72739SThierry Reding 1540dec72739SThierry Reding INIT_LIST_HEAD(&dsi->client.list); 1541dec72739SThierry Reding dsi->client.ops = &dsi_client_ops; 1542dec72739SThierry Reding dsi->client.dev = &pdev->dev; 1543dec72739SThierry Reding 1544dec72739SThierry Reding err = host1x_client_register(&dsi->client); 1545dec72739SThierry Reding if (err < 0) { 1546dec72739SThierry Reding dev_err(&pdev->dev, "failed to register host1x client: %d\n", 1547dec72739SThierry Reding err); 1548d2d0a9d2SThierry Reding goto unregister; 1549dec72739SThierry Reding } 1550dec72739SThierry Reding 1551dec72739SThierry Reding platform_set_drvdata(pdev, dsi); 1552dec72739SThierry Reding 1553dec72739SThierry Reding return 0; 1554d2d0a9d2SThierry Reding 1555d2d0a9d2SThierry Reding unregister: 1556d2d0a9d2SThierry Reding mipi_dsi_host_unregister(&dsi->host); 1557d2d0a9d2SThierry Reding mipi_free: 1558d2d0a9d2SThierry Reding tegra_mipi_free(dsi->mipi); 1559d2d0a9d2SThierry Reding disable_vdd: 1560d2d0a9d2SThierry Reding regulator_disable(dsi->vdd); 1561d2d0a9d2SThierry Reding disable_clk_lp: 1562d2d0a9d2SThierry Reding clk_disable_unprepare(dsi->clk_lp); 1563d2d0a9d2SThierry Reding disable_clk: 1564d2d0a9d2SThierry Reding clk_disable_unprepare(dsi->clk); 1565d2d0a9d2SThierry Reding reset: 1566d2d0a9d2SThierry Reding reset_control_assert(dsi->rst); 1567d2d0a9d2SThierry Reding return err; 1568dec72739SThierry Reding } 1569dec72739SThierry Reding 1570dec72739SThierry Reding static int tegra_dsi_remove(struct platform_device *pdev) 1571dec72739SThierry Reding { 1572dec72739SThierry Reding struct tegra_dsi *dsi = platform_get_drvdata(pdev); 1573dec72739SThierry Reding int err; 1574dec72739SThierry Reding 1575dec72739SThierry Reding err = host1x_client_unregister(&dsi->client); 1576dec72739SThierry Reding if (err < 0) { 1577dec72739SThierry Reding dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", 1578dec72739SThierry Reding err); 1579dec72739SThierry Reding return err; 1580dec72739SThierry Reding } 1581dec72739SThierry Reding 1582328ec69eSThierry Reding tegra_output_remove(&dsi->output); 15835b901e78SThierry Reding 1584dec72739SThierry Reding mipi_dsi_host_unregister(&dsi->host); 1585dec72739SThierry Reding tegra_mipi_free(dsi->mipi); 1586dec72739SThierry Reding 15873b077afbSThierry Reding regulator_disable(dsi->vdd); 1588dec72739SThierry Reding clk_disable_unprepare(dsi->clk_lp); 1589dec72739SThierry Reding clk_disable_unprepare(dsi->clk); 1590cb825d89SThierry Reding reset_control_assert(dsi->rst); 1591dec72739SThierry Reding 1592dec72739SThierry Reding return 0; 1593dec72739SThierry Reding } 1594dec72739SThierry Reding 1595dec72739SThierry Reding static const struct of_device_id tegra_dsi_of_match[] = { 1596dec72739SThierry Reding { .compatible = "nvidia,tegra114-dsi", }, 1597dec72739SThierry Reding { }, 1598dec72739SThierry Reding }; 1599ef70728cSStephen Warren MODULE_DEVICE_TABLE(of, tegra_dsi_of_match); 1600dec72739SThierry Reding 1601dec72739SThierry Reding struct platform_driver tegra_dsi_driver = { 1602dec72739SThierry Reding .driver = { 1603dec72739SThierry Reding .name = "tegra-dsi", 1604dec72739SThierry Reding .of_match_table = tegra_dsi_of_match, 1605dec72739SThierry Reding }, 1606dec72739SThierry Reding .probe = tegra_dsi_probe, 1607dec72739SThierry Reding .remove = tegra_dsi_remove, 1608dec72739SThierry Reding }; 1609