cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dss.c (27387B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * linux/drivers/video/omap2/dss/dss.c
      4 *
      5 * Copyright (C) 2009 Nokia Corporation
      6 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
      7 *
      8 * Some code and ideas taken from drivers/video/omap/ driver
      9 * by Imre Deak.
     10 */
     11
     12#define DSS_SUBSYS_NAME "DSS"
     13
     14#include <linux/kernel.h>
     15#include <linux/module.h>
     16#include <linux/io.h>
     17#include <linux/export.h>
     18#include <linux/err.h>
     19#include <linux/delay.h>
     20#include <linux/seq_file.h>
     21#include <linux/clk.h>
     22#include <linux/platform_device.h>
     23#include <linux/pm_runtime.h>
     24#include <linux/gfp.h>
     25#include <linux/sizes.h>
     26#include <linux/mfd/syscon.h>
     27#include <linux/regmap.h>
     28#include <linux/of.h>
     29#include <linux/regulator/consumer.h>
     30#include <linux/suspend.h>
     31#include <linux/component.h>
     32#include <linux/pinctrl/consumer.h>
     33
     34#include <video/omapfb_dss.h>
     35
     36#include "dss.h"
     37#include "dss_features.h"
     38
     39#define DSS_SZ_REGS			SZ_512
     40
     41struct dss_reg {
     42	u16 idx;
     43};
     44
     45#define DSS_REG(idx)			((const struct dss_reg) { idx })
     46
     47#define DSS_REVISION			DSS_REG(0x0000)
     48#define DSS_SYSCONFIG			DSS_REG(0x0010)
     49#define DSS_SYSSTATUS			DSS_REG(0x0014)
     50#define DSS_CONTROL			DSS_REG(0x0040)
     51#define DSS_SDI_CONTROL			DSS_REG(0x0044)
     52#define DSS_PLL_CONTROL			DSS_REG(0x0048)
     53#define DSS_SDI_STATUS			DSS_REG(0x005C)
     54
     55#define REG_GET(idx, start, end) \
     56	FLD_GET(dss_read_reg(idx), start, end)
     57
     58#define REG_FLD_MOD(idx, val, start, end) \
     59	dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
     60
     61struct dss_features {
     62	u8 fck_div_max;
     63	u8 dss_fck_multiplier;
     64	const char *parent_clk_name;
     65	const enum omap_display_type *ports;
     66	int num_ports;
     67	int (*dpi_select_source)(int port, enum omap_channel channel);
     68};
     69
     70static struct {
     71	struct platform_device *pdev;
     72	void __iomem    *base;
     73	struct regmap	*syscon_pll_ctrl;
     74	u32		syscon_pll_ctrl_offset;
     75
     76	struct clk	*parent_clk;
     77	struct clk	*dss_clk;
     78	unsigned long	dss_clk_rate;
     79
     80	unsigned long	cache_req_pck;
     81	unsigned long	cache_prate;
     82	struct dispc_clock_info cache_dispc_cinfo;
     83
     84	enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI];
     85	enum omap_dss_clk_source dispc_clk_source;
     86	enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
     87
     88	bool		ctx_valid;
     89	u32		ctx[DSS_SZ_REGS / sizeof(u32)];
     90
     91	const struct dss_features *feat;
     92
     93	struct dss_pll	*video1_pll;
     94	struct dss_pll	*video2_pll;
     95} dss;
     96
     97static const char * const dss_generic_clk_source_names[] = {
     98	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI_PLL_HSDIV_DISPC",
     99	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DSI_PLL_HSDIV_DSI",
    100	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCK",
    101	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC]	= "DSI_PLL2_HSDIV_DISPC",
    102	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "DSI_PLL2_HSDIV_DSI",
    103};
    104
    105static bool dss_initialized;
    106
    107bool omapdss_is_initialized(void)
    108{
    109	return dss_initialized;
    110}
    111EXPORT_SYMBOL(omapdss_is_initialized);
    112
    113static inline void dss_write_reg(const struct dss_reg idx, u32 val)
    114{
    115	__raw_writel(val, dss.base + idx.idx);
    116}
    117
    118static inline u32 dss_read_reg(const struct dss_reg idx)
    119{
    120	return __raw_readl(dss.base + idx.idx);
    121}
    122
    123#define SR(reg) \
    124	dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
    125#define RR(reg) \
    126	dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
    127
    128static void dss_save_context(void)
    129{
    130	DSSDBG("dss_save_context\n");
    131
    132	SR(CONTROL);
    133
    134	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
    135			OMAP_DISPLAY_TYPE_SDI) {
    136		SR(SDI_CONTROL);
    137		SR(PLL_CONTROL);
    138	}
    139
    140	dss.ctx_valid = true;
    141
    142	DSSDBG("context saved\n");
    143}
    144
    145static void dss_restore_context(void)
    146{
    147	DSSDBG("dss_restore_context\n");
    148
    149	if (!dss.ctx_valid)
    150		return;
    151
    152	RR(CONTROL);
    153
    154	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
    155			OMAP_DISPLAY_TYPE_SDI) {
    156		RR(SDI_CONTROL);
    157		RR(PLL_CONTROL);
    158	}
    159
    160	DSSDBG("context restored\n");
    161}
    162
    163#undef SR
    164#undef RR
    165
    166void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable)
    167{
    168	unsigned shift;
    169	unsigned val;
    170
    171	if (!dss.syscon_pll_ctrl)
    172		return;
    173
    174	val = !enable;
    175
    176	switch (pll_id) {
    177	case DSS_PLL_VIDEO1:
    178		shift = 0;
    179		break;
    180	case DSS_PLL_VIDEO2:
    181		shift = 1;
    182		break;
    183	case DSS_PLL_HDMI:
    184		shift = 2;
    185		break;
    186	default:
    187		DSSERR("illegal DSS PLL ID %d\n", pll_id);
    188		return;
    189	}
    190
    191	regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset,
    192		1 << shift, val << shift);
    193}
    194
    195void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id,
    196	enum omap_channel channel)
    197{
    198	unsigned shift, val;
    199
    200	if (!dss.syscon_pll_ctrl)
    201		return;
    202
    203	switch (channel) {
    204	case OMAP_DSS_CHANNEL_LCD:
    205		shift = 3;
    206
    207		switch (pll_id) {
    208		case DSS_PLL_VIDEO1:
    209			val = 0; break;
    210		case DSS_PLL_HDMI:
    211			val = 1; break;
    212		default:
    213			DSSERR("error in PLL mux config for LCD\n");
    214			return;
    215		}
    216
    217		break;
    218	case OMAP_DSS_CHANNEL_LCD2:
    219		shift = 5;
    220
    221		switch (pll_id) {
    222		case DSS_PLL_VIDEO1:
    223			val = 0; break;
    224		case DSS_PLL_VIDEO2:
    225			val = 1; break;
    226		case DSS_PLL_HDMI:
    227			val = 2; break;
    228		default:
    229			DSSERR("error in PLL mux config for LCD2\n");
    230			return;
    231		}
    232
    233		break;
    234	case OMAP_DSS_CHANNEL_LCD3:
    235		shift = 7;
    236
    237		switch (pll_id) {
    238		case DSS_PLL_VIDEO1:
    239			val = 1; break;
    240		case DSS_PLL_VIDEO2:
    241			val = 0; break;
    242		case DSS_PLL_HDMI:
    243			val = 2; break;
    244		default:
    245			DSSERR("error in PLL mux config for LCD3\n");
    246			return;
    247		}
    248
    249		break;
    250	default:
    251		DSSERR("error in PLL mux config\n");
    252		return;
    253	}
    254
    255	regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset,
    256		0x3 << shift, val << shift);
    257}
    258
    259void dss_sdi_init(int datapairs)
    260{
    261	u32 l;
    262
    263	BUG_ON(datapairs > 3 || datapairs < 1);
    264
    265	l = dss_read_reg(DSS_SDI_CONTROL);
    266	l = FLD_MOD(l, 0xf, 19, 15);		/* SDI_PDIV */
    267	l = FLD_MOD(l, datapairs-1, 3, 2);	/* SDI_PRSEL */
    268	l = FLD_MOD(l, 2, 1, 0);		/* SDI_BWSEL */
    269	dss_write_reg(DSS_SDI_CONTROL, l);
    270
    271	l = dss_read_reg(DSS_PLL_CONTROL);
    272	l = FLD_MOD(l, 0x7, 25, 22);	/* SDI_PLL_FREQSEL */
    273	l = FLD_MOD(l, 0xb, 16, 11);	/* SDI_PLL_REGN */
    274	l = FLD_MOD(l, 0xb4, 10, 1);	/* SDI_PLL_REGM */
    275	dss_write_reg(DSS_PLL_CONTROL, l);
    276}
    277
    278int dss_sdi_enable(void)
    279{
    280	unsigned long timeout;
    281
    282	dispc_pck_free_enable(1);
    283
    284	/* Reset SDI PLL */
    285	REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
    286	udelay(1);	/* wait 2x PCLK */
    287
    288	/* Lock SDI PLL */
    289	REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
    290
    291	/* Waiting for PLL lock request to complete */
    292	timeout = jiffies + msecs_to_jiffies(500);
    293	while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
    294		if (time_after_eq(jiffies, timeout)) {
    295			DSSERR("PLL lock request timed out\n");
    296			goto err1;
    297		}
    298	}
    299
    300	/* Clearing PLL_GO bit */
    301	REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
    302
    303	/* Waiting for PLL to lock */
    304	timeout = jiffies + msecs_to_jiffies(500);
    305	while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
    306		if (time_after_eq(jiffies, timeout)) {
    307			DSSERR("PLL lock timed out\n");
    308			goto err1;
    309		}
    310	}
    311
    312	dispc_lcd_enable_signal(1);
    313
    314	/* Waiting for SDI reset to complete */
    315	timeout = jiffies + msecs_to_jiffies(500);
    316	while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
    317		if (time_after_eq(jiffies, timeout)) {
    318			DSSERR("SDI reset timed out\n");
    319			goto err2;
    320		}
    321	}
    322
    323	return 0;
    324
    325 err2:
    326	dispc_lcd_enable_signal(0);
    327 err1:
    328	/* Reset SDI PLL */
    329	REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
    330
    331	dispc_pck_free_enable(0);
    332
    333	return -ETIMEDOUT;
    334}
    335
    336void dss_sdi_disable(void)
    337{
    338	dispc_lcd_enable_signal(0);
    339
    340	dispc_pck_free_enable(0);
    341
    342	/* Reset SDI PLL */
    343	REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
    344}
    345
    346const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
    347{
    348	return dss_generic_clk_source_names[clk_src];
    349}
    350
    351void dss_dump_clocks(struct seq_file *s)
    352{
    353	const char *fclk_name, *fclk_real_name;
    354	unsigned long fclk_rate;
    355
    356	if (dss_runtime_get())
    357		return;
    358
    359	seq_printf(s, "- DSS -\n");
    360
    361	fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
    362	fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
    363	fclk_rate = clk_get_rate(dss.dss_clk);
    364
    365	seq_printf(s, "%s (%s) = %lu\n",
    366			fclk_name, fclk_real_name,
    367			fclk_rate);
    368
    369	dss_runtime_put();
    370}
    371
    372static void dss_dump_regs(struct seq_file *s)
    373{
    374#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
    375
    376	if (dss_runtime_get())
    377		return;
    378
    379	DUMPREG(DSS_REVISION);
    380	DUMPREG(DSS_SYSCONFIG);
    381	DUMPREG(DSS_SYSSTATUS);
    382	DUMPREG(DSS_CONTROL);
    383
    384	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
    385			OMAP_DISPLAY_TYPE_SDI) {
    386		DUMPREG(DSS_SDI_CONTROL);
    387		DUMPREG(DSS_PLL_CONTROL);
    388		DUMPREG(DSS_SDI_STATUS);
    389	}
    390
    391	dss_runtime_put();
    392#undef DUMPREG
    393}
    394
    395static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
    396{
    397	int b;
    398	u8 start, end;
    399
    400	switch (clk_src) {
    401	case OMAP_DSS_CLK_SRC_FCK:
    402		b = 0;
    403		break;
    404	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
    405		b = 1;
    406		break;
    407	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
    408		b = 2;
    409		break;
    410	default:
    411		BUG();
    412		return;
    413	}
    414
    415	dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
    416
    417	REG_FLD_MOD(DSS_CONTROL, b, start, end);	/* DISPC_CLK_SWITCH */
    418
    419	dss.dispc_clk_source = clk_src;
    420}
    421
    422void dss_select_dsi_clk_source(int dsi_module,
    423		enum omap_dss_clk_source clk_src)
    424{
    425	int b, pos;
    426
    427	switch (clk_src) {
    428	case OMAP_DSS_CLK_SRC_FCK:
    429		b = 0;
    430		break;
    431	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
    432		BUG_ON(dsi_module != 0);
    433		b = 1;
    434		break;
    435	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
    436		BUG_ON(dsi_module != 1);
    437		b = 1;
    438		break;
    439	default:
    440		BUG();
    441		return;
    442	}
    443
    444	pos = dsi_module == 0 ? 1 : 10;
    445	REG_FLD_MOD(DSS_CONTROL, b, pos, pos);	/* DSIx_CLK_SWITCH */
    446
    447	dss.dsi_clk_source[dsi_module] = clk_src;
    448}
    449
    450void dss_select_lcd_clk_source(enum omap_channel channel,
    451		enum omap_dss_clk_source clk_src)
    452{
    453	int b, ix, pos;
    454
    455	if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
    456		dss_select_dispc_clk_source(clk_src);
    457		return;
    458	}
    459
    460	switch (clk_src) {
    461	case OMAP_DSS_CLK_SRC_FCK:
    462		b = 0;
    463		break;
    464	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
    465		BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
    466		b = 1;
    467		break;
    468	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
    469		BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
    470		       channel != OMAP_DSS_CHANNEL_LCD3);
    471		b = 1;
    472		break;
    473	default:
    474		BUG();
    475		return;
    476	}
    477
    478	pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
    479	     (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
    480	REG_FLD_MOD(DSS_CONTROL, b, pos, pos);	/* LCDx_CLK_SWITCH */
    481
    482	ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
    483	    (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
    484	dss.lcd_clk_source[ix] = clk_src;
    485}
    486
    487enum omap_dss_clk_source dss_get_dispc_clk_source(void)
    488{
    489	return dss.dispc_clk_source;
    490}
    491
    492enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
    493{
    494	return dss.dsi_clk_source[dsi_module];
    495}
    496
    497enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
    498{
    499	if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
    500		int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
    501			(channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
    502		return dss.lcd_clk_source[ix];
    503	} else {
    504		/* LCD_CLK source is the same as DISPC_FCLK source for
    505		 * OMAP2 and OMAP3 */
    506		return dss.dispc_clk_source;
    507	}
    508}
    509
    510bool dss_div_calc(unsigned long pck, unsigned long fck_min,
    511		dss_div_calc_func func, void *data)
    512{
    513	int fckd, fckd_start, fckd_stop;
    514	unsigned long fck;
    515	unsigned long fck_hw_max;
    516	unsigned long fckd_hw_max;
    517	unsigned long prate;
    518	unsigned m;
    519
    520	fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
    521
    522	if (dss.parent_clk == NULL) {
    523		unsigned pckd;
    524
    525		pckd = fck_hw_max / pck;
    526
    527		fck = pck * pckd;
    528
    529		fck = clk_round_rate(dss.dss_clk, fck);
    530
    531		return func(fck, data);
    532	}
    533
    534	fckd_hw_max = dss.feat->fck_div_max;
    535
    536	m = dss.feat->dss_fck_multiplier;
    537	prate = clk_get_rate(dss.parent_clk);
    538
    539	fck_min = fck_min ? fck_min : 1;
    540
    541	fckd_start = min(prate * m / fck_min, fckd_hw_max);
    542	fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
    543
    544	for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
    545		fck = DIV_ROUND_UP(prate, fckd) * m;
    546
    547		if (func(fck, data))
    548			return true;
    549	}
    550
    551	return false;
    552}
    553
    554int dss_set_fck_rate(unsigned long rate)
    555{
    556	int r;
    557
    558	DSSDBG("set fck to %lu\n", rate);
    559
    560	r = clk_set_rate(dss.dss_clk, rate);
    561	if (r)
    562		return r;
    563
    564	dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
    565
    566	WARN_ONCE(dss.dss_clk_rate != rate,
    567			"clk rate mismatch: %lu != %lu", dss.dss_clk_rate,
    568			rate);
    569
    570	return 0;
    571}
    572
    573unsigned long dss_get_dispc_clk_rate(void)
    574{
    575	return dss.dss_clk_rate;
    576}
    577
    578static int dss_setup_default_clock(void)
    579{
    580	unsigned long max_dss_fck, prate;
    581	unsigned long fck;
    582	unsigned fck_div;
    583	int r;
    584
    585	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
    586
    587	if (dss.parent_clk == NULL) {
    588		fck = clk_round_rate(dss.dss_clk, max_dss_fck);
    589	} else {
    590		prate = clk_get_rate(dss.parent_clk);
    591
    592		fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
    593				max_dss_fck);
    594		fck = DIV_ROUND_UP(prate, fck_div) * dss.feat->dss_fck_multiplier;
    595	}
    596
    597	r = dss_set_fck_rate(fck);
    598	if (r)
    599		return r;
    600
    601	return 0;
    602}
    603
    604void dss_set_venc_output(enum omap_dss_venc_type type)
    605{
    606	int l = 0;
    607
    608	if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
    609		l = 0;
    610	else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
    611		l = 1;
    612	else
    613		BUG();
    614
    615	/* venc out selection. 0 = comp, 1 = svideo */
    616	REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
    617}
    618
    619void dss_set_dac_pwrdn_bgz(bool enable)
    620{
    621	REG_FLD_MOD(DSS_CONTROL, enable, 5, 5);	/* DAC Power-Down Control */
    622}
    623
    624void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
    625{
    626	enum omap_display_type dp;
    627	dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
    628
    629	/* Complain about invalid selections */
    630	WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
    631	WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
    632
    633	/* Select only if we have options */
    634	if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
    635		REG_FLD_MOD(DSS_CONTROL, src, 15, 15);	/* VENC_HDMI_SWITCH */
    636}
    637
    638enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
    639{
    640	enum omap_display_type displays;
    641
    642	displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
    643	if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
    644		return DSS_VENC_TV_CLK;
    645
    646	if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
    647		return DSS_HDMI_M_PCLK;
    648
    649	return REG_GET(DSS_CONTROL, 15, 15);
    650}
    651
    652static int dss_dpi_select_source_omap2_omap3(int port, enum omap_channel channel)
    653{
    654	if (channel != OMAP_DSS_CHANNEL_LCD)
    655		return -EINVAL;
    656
    657	return 0;
    658}
    659
    660static int dss_dpi_select_source_omap4(int port, enum omap_channel channel)
    661{
    662	int val;
    663
    664	switch (channel) {
    665	case OMAP_DSS_CHANNEL_LCD2:
    666		val = 0;
    667		break;
    668	case OMAP_DSS_CHANNEL_DIGIT:
    669		val = 1;
    670		break;
    671	default:
    672		return -EINVAL;
    673	}
    674
    675	REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
    676
    677	return 0;
    678}
    679
    680static int dss_dpi_select_source_omap5(int port, enum omap_channel channel)
    681{
    682	int val;
    683
    684	switch (channel) {
    685	case OMAP_DSS_CHANNEL_LCD:
    686		val = 1;
    687		break;
    688	case OMAP_DSS_CHANNEL_LCD2:
    689		val = 2;
    690		break;
    691	case OMAP_DSS_CHANNEL_LCD3:
    692		val = 3;
    693		break;
    694	case OMAP_DSS_CHANNEL_DIGIT:
    695		val = 0;
    696		break;
    697	default:
    698		return -EINVAL;
    699	}
    700
    701	REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
    702
    703	return 0;
    704}
    705
    706static int dss_dpi_select_source_dra7xx(int port, enum omap_channel channel)
    707{
    708	switch (port) {
    709	case 0:
    710		return dss_dpi_select_source_omap5(port, channel);
    711	case 1:
    712		if (channel != OMAP_DSS_CHANNEL_LCD2)
    713			return -EINVAL;
    714		break;
    715	case 2:
    716		if (channel != OMAP_DSS_CHANNEL_LCD3)
    717			return -EINVAL;
    718		break;
    719	default:
    720		return -EINVAL;
    721	}
    722
    723	return 0;
    724}
    725
    726int dss_dpi_select_source(int port, enum omap_channel channel)
    727{
    728	return dss.feat->dpi_select_source(port, channel);
    729}
    730
    731static int dss_get_clocks(void)
    732{
    733	struct clk *clk;
    734
    735	clk = devm_clk_get(&dss.pdev->dev, "fck");
    736	if (IS_ERR(clk)) {
    737		DSSERR("can't get clock fck\n");
    738		return PTR_ERR(clk);
    739	}
    740
    741	dss.dss_clk = clk;
    742
    743	if (dss.feat->parent_clk_name) {
    744		clk = clk_get(NULL, dss.feat->parent_clk_name);
    745		if (IS_ERR(clk)) {
    746			DSSERR("Failed to get %s\n", dss.feat->parent_clk_name);
    747			return PTR_ERR(clk);
    748		}
    749	} else {
    750		clk = NULL;
    751	}
    752
    753	dss.parent_clk = clk;
    754
    755	return 0;
    756}
    757
    758static void dss_put_clocks(void)
    759{
    760	if (dss.parent_clk)
    761		clk_put(dss.parent_clk);
    762}
    763
    764int dss_runtime_get(void)
    765{
    766	int r;
    767
    768	DSSDBG("dss_runtime_get\n");
    769
    770	r = pm_runtime_get_sync(&dss.pdev->dev);
    771	if (WARN_ON(r < 0)) {
    772		pm_runtime_put_sync(&dss.pdev->dev);
    773		return r;
    774	}
    775	return 0;
    776}
    777
    778void dss_runtime_put(void)
    779{
    780	int r;
    781
    782	DSSDBG("dss_runtime_put\n");
    783
    784	r = pm_runtime_put_sync(&dss.pdev->dev);
    785	WARN_ON(r < 0 && r != -ENOSYS && r != -EBUSY);
    786}
    787
    788/* DEBUGFS */
    789#if defined(CONFIG_FB_OMAP2_DSS_DEBUGFS)
    790void dss_debug_dump_clocks(struct seq_file *s)
    791{
    792	dss_dump_clocks(s);
    793	dispc_dump_clocks(s);
    794#ifdef CONFIG_FB_OMAP2_DSS_DSI
    795	dsi_dump_clocks(s);
    796#endif
    797}
    798#endif
    799
    800
    801static const enum omap_display_type omap2plus_ports[] = {
    802	OMAP_DISPLAY_TYPE_DPI,
    803};
    804
    805static const enum omap_display_type omap34xx_ports[] = {
    806	OMAP_DISPLAY_TYPE_DPI,
    807	OMAP_DISPLAY_TYPE_SDI,
    808};
    809
    810static const enum omap_display_type dra7xx_ports[] = {
    811	OMAP_DISPLAY_TYPE_DPI,
    812	OMAP_DISPLAY_TYPE_DPI,
    813	OMAP_DISPLAY_TYPE_DPI,
    814};
    815
    816static const struct dss_features omap24xx_dss_feats = {
    817	/*
    818	 * fck div max is really 16, but the divider range has gaps. The range
    819	 * from 1 to 6 has no gaps, so let's use that as a max.
    820	 */
    821	.fck_div_max		=	6,
    822	.dss_fck_multiplier	=	2,
    823	.parent_clk_name	=	"core_ck",
    824	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
    825	.ports			=	omap2plus_ports,
    826	.num_ports		=	ARRAY_SIZE(omap2plus_ports),
    827};
    828
    829static const struct dss_features omap34xx_dss_feats = {
    830	.fck_div_max		=	16,
    831	.dss_fck_multiplier	=	2,
    832	.parent_clk_name	=	"dpll4_ck",
    833	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
    834	.ports			=	omap34xx_ports,
    835	.num_ports		=	ARRAY_SIZE(omap34xx_ports),
    836};
    837
    838static const struct dss_features omap3630_dss_feats = {
    839	.fck_div_max		=	31,
    840	.dss_fck_multiplier	=	1,
    841	.parent_clk_name	=	"dpll4_ck",
    842	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
    843	.ports			=	omap2plus_ports,
    844	.num_ports		=	ARRAY_SIZE(omap2plus_ports),
    845};
    846
    847static const struct dss_features omap44xx_dss_feats = {
    848	.fck_div_max		=	32,
    849	.dss_fck_multiplier	=	1,
    850	.parent_clk_name	=	"dpll_per_x2_ck",
    851	.dpi_select_source	=	&dss_dpi_select_source_omap4,
    852	.ports			=	omap2plus_ports,
    853	.num_ports		=	ARRAY_SIZE(omap2plus_ports),
    854};
    855
    856static const struct dss_features omap54xx_dss_feats = {
    857	.fck_div_max		=	64,
    858	.dss_fck_multiplier	=	1,
    859	.parent_clk_name	=	"dpll_per_x2_ck",
    860	.dpi_select_source	=	&dss_dpi_select_source_omap5,
    861	.ports			=	omap2plus_ports,
    862	.num_ports		=	ARRAY_SIZE(omap2plus_ports),
    863};
    864
    865static const struct dss_features am43xx_dss_feats = {
    866	.fck_div_max		=	0,
    867	.dss_fck_multiplier	=	0,
    868	.parent_clk_name	=	NULL,
    869	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
    870	.ports			=	omap2plus_ports,
    871	.num_ports		=	ARRAY_SIZE(omap2plus_ports),
    872};
    873
    874static const struct dss_features dra7xx_dss_feats = {
    875	.fck_div_max		=	64,
    876	.dss_fck_multiplier	=	1,
    877	.parent_clk_name	=	"dpll_per_x2_ck",
    878	.dpi_select_source	=	&dss_dpi_select_source_dra7xx,
    879	.ports			=	dra7xx_ports,
    880	.num_ports		=	ARRAY_SIZE(dra7xx_ports),
    881};
    882
    883static const struct dss_features *dss_get_features(void)
    884{
    885	switch (omapdss_get_version()) {
    886	case OMAPDSS_VER_OMAP24xx:
    887		return &omap24xx_dss_feats;
    888
    889	case OMAPDSS_VER_OMAP34xx_ES1:
    890	case OMAPDSS_VER_OMAP34xx_ES3:
    891	case OMAPDSS_VER_AM35xx:
    892		return &omap34xx_dss_feats;
    893
    894	case OMAPDSS_VER_OMAP3630:
    895		return &omap3630_dss_feats;
    896
    897	case OMAPDSS_VER_OMAP4430_ES1:
    898	case OMAPDSS_VER_OMAP4430_ES2:
    899	case OMAPDSS_VER_OMAP4:
    900		return &omap44xx_dss_feats;
    901
    902	case OMAPDSS_VER_OMAP5:
    903		return &omap54xx_dss_feats;
    904
    905	case OMAPDSS_VER_AM43xx:
    906		return &am43xx_dss_feats;
    907
    908	case OMAPDSS_VER_DRA7xx:
    909		return &dra7xx_dss_feats;
    910
    911	default:
    912		return NULL;
    913	}
    914}
    915
    916static void dss_uninit_ports(struct platform_device *pdev);
    917
    918static int dss_init_ports(struct platform_device *pdev)
    919{
    920	struct device_node *parent = pdev->dev.of_node;
    921	struct device_node *port;
    922	int r, ret = 0;
    923
    924	if (parent == NULL)
    925		return 0;
    926
    927	port = omapdss_of_get_next_port(parent, NULL);
    928	if (!port)
    929		return 0;
    930
    931	if (dss.feat->num_ports == 0)
    932		return 0;
    933
    934	do {
    935		enum omap_display_type port_type;
    936		u32 reg;
    937
    938		r = of_property_read_u32(port, "reg", &reg);
    939		if (r)
    940			reg = 0;
    941
    942		if (reg >= dss.feat->num_ports)
    943			continue;
    944
    945		port_type = dss.feat->ports[reg];
    946
    947		switch (port_type) {
    948		case OMAP_DISPLAY_TYPE_DPI:
    949			ret = dpi_init_port(pdev, port);
    950			break;
    951		case OMAP_DISPLAY_TYPE_SDI:
    952			ret = sdi_init_port(pdev, port);
    953			break;
    954		default:
    955			break;
    956		}
    957	} while (!ret &&
    958		 (port = omapdss_of_get_next_port(parent, port)) != NULL);
    959
    960	if (ret)
    961		dss_uninit_ports(pdev);
    962
    963	return ret;
    964}
    965
    966static void dss_uninit_ports(struct platform_device *pdev)
    967{
    968	struct device_node *parent = pdev->dev.of_node;
    969	struct device_node *port;
    970
    971	if (parent == NULL)
    972		return;
    973
    974	port = omapdss_of_get_next_port(parent, NULL);
    975	if (!port)
    976		return;
    977
    978	if (dss.feat->num_ports == 0)
    979		return;
    980
    981	do {
    982		enum omap_display_type port_type;
    983		u32 reg;
    984		int r;
    985
    986		r = of_property_read_u32(port, "reg", &reg);
    987		if (r)
    988			reg = 0;
    989
    990		if (reg >= dss.feat->num_ports)
    991			continue;
    992
    993		port_type = dss.feat->ports[reg];
    994
    995		switch (port_type) {
    996		case OMAP_DISPLAY_TYPE_DPI:
    997			dpi_uninit_port(port);
    998			break;
    999		case OMAP_DISPLAY_TYPE_SDI:
   1000			sdi_uninit_port(port);
   1001			break;
   1002		default:
   1003			break;
   1004		}
   1005	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
   1006}
   1007
   1008static int dss_video_pll_probe(struct platform_device *pdev)
   1009{
   1010	struct device_node *np = pdev->dev.of_node;
   1011	struct regulator *pll_regulator;
   1012	int r;
   1013
   1014	if (!np)
   1015		return 0;
   1016
   1017	if (of_property_read_bool(np, "syscon-pll-ctrl")) {
   1018		dss.syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np,
   1019			"syscon-pll-ctrl");
   1020		if (IS_ERR(dss.syscon_pll_ctrl)) {
   1021			dev_err(&pdev->dev,
   1022				"failed to get syscon-pll-ctrl regmap\n");
   1023			return PTR_ERR(dss.syscon_pll_ctrl);
   1024		}
   1025
   1026		if (of_property_read_u32_index(np, "syscon-pll-ctrl", 1,
   1027				&dss.syscon_pll_ctrl_offset)) {
   1028			dev_err(&pdev->dev,
   1029				"failed to get syscon-pll-ctrl offset\n");
   1030			return -EINVAL;
   1031		}
   1032	}
   1033
   1034	pll_regulator = devm_regulator_get(&pdev->dev, "vdda_video");
   1035	if (IS_ERR(pll_regulator)) {
   1036		r = PTR_ERR(pll_regulator);
   1037
   1038		switch (r) {
   1039		case -ENOENT:
   1040			pll_regulator = NULL;
   1041			break;
   1042
   1043		case -EPROBE_DEFER:
   1044			return -EPROBE_DEFER;
   1045
   1046		default:
   1047			DSSERR("can't get DPLL VDDA regulator\n");
   1048			return r;
   1049		}
   1050	}
   1051
   1052	if (of_property_match_string(np, "reg-names", "pll1") >= 0) {
   1053		dss.video1_pll = dss_video_pll_init(pdev, 0, pll_regulator);
   1054		if (IS_ERR(dss.video1_pll))
   1055			return PTR_ERR(dss.video1_pll);
   1056	}
   1057
   1058	if (of_property_match_string(np, "reg-names", "pll2") >= 0) {
   1059		dss.video2_pll = dss_video_pll_init(pdev, 1, pll_regulator);
   1060		if (IS_ERR(dss.video2_pll)) {
   1061			dss_video_pll_uninit(dss.video1_pll);
   1062			return PTR_ERR(dss.video2_pll);
   1063		}
   1064	}
   1065
   1066	return 0;
   1067}
   1068
   1069/* DSS HW IP initialisation */
   1070static int dss_bind(struct device *dev)
   1071{
   1072	struct platform_device *pdev = to_platform_device(dev);
   1073	struct resource *dss_mem;
   1074	u32 rev;
   1075	int r;
   1076
   1077	dss.pdev = pdev;
   1078
   1079	dss.feat = dss_get_features();
   1080	if (!dss.feat)
   1081		return -ENODEV;
   1082
   1083	dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
   1084	if (!dss_mem) {
   1085		DSSERR("can't get IORESOURCE_MEM DSS\n");
   1086		return -EINVAL;
   1087	}
   1088
   1089	dss.base = devm_ioremap(&pdev->dev, dss_mem->start,
   1090				resource_size(dss_mem));
   1091	if (!dss.base) {
   1092		DSSERR("can't ioremap DSS\n");
   1093		return -ENOMEM;
   1094	}
   1095
   1096	r = dss_get_clocks();
   1097	if (r)
   1098		return r;
   1099
   1100	r = dss_setup_default_clock();
   1101	if (r)
   1102		goto err_setup_clocks;
   1103
   1104	r = dss_video_pll_probe(pdev);
   1105	if (r)
   1106		goto err_pll_init;
   1107
   1108	r = dss_init_ports(pdev);
   1109	if (r)
   1110		goto err_init_ports;
   1111
   1112	pm_runtime_enable(&pdev->dev);
   1113
   1114	r = dss_runtime_get();
   1115	if (r)
   1116		goto err_runtime_get;
   1117
   1118	dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
   1119
   1120	/* Select DPLL */
   1121	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
   1122
   1123	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
   1124
   1125#ifdef CONFIG_FB_OMAP2_DSS_VENC
   1126	REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);	/* venc dac demen */
   1127	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
   1128	REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);	/* venc clock mode = normal */
   1129#endif
   1130	dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
   1131	dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
   1132	dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
   1133	dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
   1134	dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
   1135
   1136	rev = dss_read_reg(DSS_REVISION);
   1137	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
   1138			FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
   1139
   1140	dss_runtime_put();
   1141
   1142	r = component_bind_all(&pdev->dev, NULL);
   1143	if (r)
   1144		goto err_component;
   1145
   1146	dss_debugfs_create_file("dss", dss_dump_regs);
   1147
   1148	pm_set_vt_switch(0);
   1149
   1150	dss_initialized = true;
   1151
   1152	return 0;
   1153
   1154err_component:
   1155err_runtime_get:
   1156	pm_runtime_disable(&pdev->dev);
   1157	dss_uninit_ports(pdev);
   1158err_init_ports:
   1159	if (dss.video1_pll)
   1160		dss_video_pll_uninit(dss.video1_pll);
   1161
   1162	if (dss.video2_pll)
   1163		dss_video_pll_uninit(dss.video2_pll);
   1164err_pll_init:
   1165err_setup_clocks:
   1166	dss_put_clocks();
   1167	return r;
   1168}
   1169
   1170static void dss_unbind(struct device *dev)
   1171{
   1172	struct platform_device *pdev = to_platform_device(dev);
   1173
   1174	dss_initialized = false;
   1175
   1176	component_unbind_all(&pdev->dev, NULL);
   1177
   1178	if (dss.video1_pll)
   1179		dss_video_pll_uninit(dss.video1_pll);
   1180
   1181	if (dss.video2_pll)
   1182		dss_video_pll_uninit(dss.video2_pll);
   1183
   1184	dss_uninit_ports(pdev);
   1185
   1186	pm_runtime_disable(&pdev->dev);
   1187
   1188	dss_put_clocks();
   1189}
   1190
   1191static const struct component_master_ops dss_component_ops = {
   1192	.bind = dss_bind,
   1193	.unbind = dss_unbind,
   1194};
   1195
   1196static int dss_add_child_component(struct device *dev, void *data)
   1197{
   1198	struct component_match **match = data;
   1199
   1200	/*
   1201	 * HACK
   1202	 * We don't have a working driver for rfbi, so skip it here always.
   1203	 * Otherwise dss will never get probed successfully, as it will wait
   1204	 * for rfbi to get probed.
   1205	 */
   1206	if (strstr(dev_name(dev), "rfbi"))
   1207		return 0;
   1208
   1209	component_match_add(dev->parent, match, component_compare_dev, dev);
   1210
   1211	return 0;
   1212}
   1213
   1214static int dss_probe(struct platform_device *pdev)
   1215{
   1216	struct component_match *match = NULL;
   1217	int r;
   1218
   1219	/* add all the child devices as components */
   1220	device_for_each_child(&pdev->dev, &match, dss_add_child_component);
   1221
   1222	r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
   1223	if (r)
   1224		return r;
   1225
   1226	return 0;
   1227}
   1228
   1229static int dss_remove(struct platform_device *pdev)
   1230{
   1231	component_master_del(&pdev->dev, &dss_component_ops);
   1232	return 0;
   1233}
   1234
   1235static int dss_runtime_suspend(struct device *dev)
   1236{
   1237	dss_save_context();
   1238	dss_set_min_bus_tput(dev, 0);
   1239
   1240	pinctrl_pm_select_sleep_state(dev);
   1241
   1242	return 0;
   1243}
   1244
   1245static int dss_runtime_resume(struct device *dev)
   1246{
   1247	int r;
   1248
   1249	pinctrl_pm_select_default_state(dev);
   1250
   1251	/*
   1252	 * Set an arbitrarily high tput request to ensure OPP100.
   1253	 * What we should really do is to make a request to stay in OPP100,
   1254	 * without any tput requirements, but that is not currently possible
   1255	 * via the PM layer.
   1256	 */
   1257
   1258	r = dss_set_min_bus_tput(dev, 1000000000);
   1259	if (r)
   1260		return r;
   1261
   1262	dss_restore_context();
   1263	return 0;
   1264}
   1265
   1266static const struct dev_pm_ops dss_pm_ops = {
   1267	.runtime_suspend = dss_runtime_suspend,
   1268	.runtime_resume = dss_runtime_resume,
   1269};
   1270
   1271static const struct of_device_id dss_of_match[] = {
   1272	{ .compatible = "ti,omap2-dss", },
   1273	{ .compatible = "ti,omap3-dss", },
   1274	{ .compatible = "ti,omap4-dss", },
   1275	{ .compatible = "ti,omap5-dss", },
   1276	{ .compatible = "ti,dra7-dss", },
   1277	{},
   1278};
   1279
   1280MODULE_DEVICE_TABLE(of, dss_of_match);
   1281
   1282static struct platform_driver omap_dsshw_driver = {
   1283	.probe		= dss_probe,
   1284	.remove		= dss_remove,
   1285	.driver         = {
   1286		.name   = "omapdss_dss",
   1287		.pm	= &dss_pm_ops,
   1288		.of_match_table = dss_of_match,
   1289		.suppress_bind_attrs = true,
   1290	},
   1291};
   1292
   1293int __init dss_init_platform_driver(void)
   1294{
   1295	return platform_driver_register(&omap_dsshw_driver);
   1296}
   1297
   1298void dss_uninit_platform_driver(void)
   1299{
   1300	platform_driver_unregister(&omap_dsshw_driver);
   1301}