File Index
Files and directories
Sign in
FILE

t1042rdb_diu.c

File preview with syntax highlighting.

linux-6.19.14/arch/powerpc/platforms/85xx/t1042rdb_diu.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * T1042 platform DIU operation
  4 *
  5 * Copyright 2014 Freescale Semiconductor Inc.
  6 */
  7
  8#include <linux/init.h>
  9#include <linux/io.h>
 10#include <linux/kernel.h>
 11#include <linux/module.h>
 12#include <linux/of.h>
 13#include <linux/of_address.h>
 14
 15#include <sysdev/fsl_soc.h>
 16
 17/*DIU Pixel ClockCR offset in scfg*/
 18#define CCSR_SCFG_PIXCLKCR      0x28
 19
 20/* DIU Pixel Clock bits of the PIXCLKCR */
 21#define PIXCLKCR_PXCKEN		0x80000000
 22#define PIXCLKCR_PXCKINV	0x40000000
 23#define PIXCLKCR_PXCKDLY	0x0000FF00
 24#define PIXCLKCR_PXCLK_MASK	0x00FF0000
 25
 26/* Some CPLD register definitions */
 27#define CPLD_DIUCSR		0x16
 28#define CPLD_DIUCSR_DVIEN	0x80
 29#define CPLD_DIUCSR_BACKLIGHT	0x0f
 30
 31struct device_node *cpld_node;
 32
 33/**
 34 * t1042rdb_set_monitor_port: switch the output to a different monitor port
 35 */
 36static void t1042rdb_set_monitor_port(enum fsl_diu_monitor_port port)
 37{
 38	void __iomem *cpld_base;
 39
 40	cpld_base = of_iomap(cpld_node, 0);
 41	if (!cpld_base) {
 42		pr_err("%s: Could not map cpld registers\n", __func__);
 43		goto exit;
 44	}
 45
 46	switch (port) {
 47	case FSL_DIU_PORT_DVI:
 48		/* Enable the DVI(HDMI) port, disable the DFP and
 49		 * the backlight
 50		 */
 51		clrbits8(cpld_base + CPLD_DIUCSR, CPLD_DIUCSR_DVIEN);
 52		break;
 53	case FSL_DIU_PORT_LVDS:
 54		/*
 55		 * LVDS also needs backlight enabled, otherwise the display
 56		 * will be blank.
 57		 */
 58		/* Enable the DFP port, disable the DVI*/
 59		setbits8(cpld_base + CPLD_DIUCSR, 0x01 << 8);
 60		setbits8(cpld_base + CPLD_DIUCSR, 0x01 << 4);
 61		setbits8(cpld_base + CPLD_DIUCSR, CPLD_DIUCSR_BACKLIGHT);
 62		break;
 63	default:
 64		pr_err("%s: Unsupported monitor port %i\n", __func__, port);
 65	}
 66
 67	iounmap(cpld_base);
 68exit:
 69	of_node_put(cpld_node);
 70}
 71
 72/**
 73 * t1042rdb_set_pixel_clock: program the DIU's clock
 74 * @pixclock: pixel clock in ps (pico seconds)
 75 */
 76static void t1042rdb_set_pixel_clock(unsigned int pixclock)
 77{
 78	struct device_node *scfg_np;
 79	void __iomem *scfg;
 80	unsigned long freq;
 81	u64 temp;
 82	u32 pxclk;
 83
 84	scfg_np = of_find_compatible_node(NULL, NULL, "fsl,t1040-scfg");
 85	if (!scfg_np) {
 86		pr_err("%s: Missing scfg node. Can not display video.\n",
 87		       __func__);
 88		return;
 89	}
 90
 91	scfg = of_iomap(scfg_np, 0);
 92	of_node_put(scfg_np);
 93	if (!scfg) {
 94		pr_err("%s: Could not map device. Can not display video.\n",
 95		       __func__);
 96		return;
 97	}
 98
 99	/* Convert pixclock into frequency */
100	temp = 1000000000000ULL;
101	do_div(temp, pixclock);
102	freq = temp;
103
104	/*
105	 * 'pxclk' is the ratio of the platform clock to the pixel clock.
106	 * This number is programmed into the PIXCLKCR register, and the valid
107	 * range of values is 2-255.
108	 */
109	pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
110	pxclk = clamp_t(u32, pxclk, 2, 255);
111
112	/* Disable the pixel clock, and set it to non-inverted and no delay */
113	clrbits32(scfg + CCSR_SCFG_PIXCLKCR,
114		  PIXCLKCR_PXCKEN | PIXCLKCR_PXCKDLY | PIXCLKCR_PXCLK_MASK);
115
116	/* Enable the clock and set the pxclk */
117	setbits32(scfg + CCSR_SCFG_PIXCLKCR, PIXCLKCR_PXCKEN | (pxclk << 16));
118
119	iounmap(scfg);
120}
121
122/**
123 * t1042rdb_valid_monitor_port: set the monitor port for sysfs
124 */
125static enum fsl_diu_monitor_port
126t1042rdb_valid_monitor_port(enum fsl_diu_monitor_port port)
127{
128	switch (port) {
129	case FSL_DIU_PORT_DVI:
130	case FSL_DIU_PORT_LVDS:
131		return port;
132	default:
133		return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
134	}
135}
136
137static int __init t1042rdb_diu_init(void)
138{
139	cpld_node = of_find_compatible_node(NULL, NULL, "fsl,t1042rdb-cpld");
140	if (!cpld_node)
141		return 0;
142
143	diu_ops.set_monitor_port	= t1042rdb_set_monitor_port;
144	diu_ops.set_pixel_clock		= t1042rdb_set_pixel_clock;
145	diu_ops.valid_monitor_port	= t1042rdb_valid_monitor_port;
146
147	return 0;
148}
149
150early_initcall(t1042rdb_diu_init);
151
152MODULE_DESCRIPTION("Freescale T1042 DIU driver");
153MODULE_LICENSE("GPL");
~/ Read-only file preview.