File Index
Files and directories
Sign in
FILE

dss.c

File preview with syntax highlighting.

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