// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
*
* Some code and ideas taken from drivers/video/omap/ driver
* by Imre Deak.
*/
#define DSS_SUBSYS_NAME "DSS"
#include <linux/debugfs.h>
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/export.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/clk.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/gfp.h>
#include <linux/sizes.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_graph.h>
#include <linux/regulator/consumer.h>
#include <linux/suspend.h>
#include <linux/component.h>
#include <linux/sys_soc.h>
#include "omapdss.h"
#include "dss.h"
struct dss_reg {
u16 idx;
};
#define DSS_REG(idx) ((const struct dss_reg) { idx })
#define DSS_REVISION DSS_REG(0x0000)
#define DSS_SYSCONFIG DSS_REG(0x0010)
#define DSS_SYSSTATUS DSS_REG(0x0014)
#define DSS_CONTROL DSS_REG(0x0040)
#define DSS_SDI_CONTROL DSS_REG(0x0044)
#define DSS_PLL_CONTROL DSS_REG(0x0048)
#define DSS_SDI_STATUS DSS_REG(0x005C)
#define REG_GET(dss, idx, start, end) \
FLD_GET(dss_read_reg(dss, idx), start, end)
#define REG_FLD_MOD(dss, idx, val, start, end) \
dss_write_reg(dss, idx, \
FLD_MOD(dss_read_reg(dss, idx), val, start, end))
struct dss_ops {
int (*dpi_select_source)(struct dss_device *dss, int port,
enum omap_channel channel);
int (*select_lcd_source)(struct dss_device *dss,
enum omap_channel channel,
enum dss_clk_source clk_src);
};
struct dss_features {
enum dss_model model;
u8 fck_div_max;
unsigned int fck_freq_max;
u8 dss_fck_multiplier;
const char *parent_clk_name;
const enum omap_display_type *ports;
int num_ports;
const enum omap_dss_output_id *outputs;
const struct dss_ops *ops;
struct dss_reg_field dispc_clk_switch;
bool has_lcd_clk_src;
};
static const char * const dss_generic_clk_source_names[] = {
[DSS_CLK_SRC_FCK] = "FCK",
[DSS_CLK_SRC_PLL1_1] = "PLL1:1",
[DSS_CLK_SRC_PLL1_2] = "PLL1:2",
[DSS_CLK_SRC_PLL1_3] = "PLL1:3",
[DSS_CLK_SRC_PLL2_1] = "PLL2:1",
[DSS_CLK_SRC_PLL2_2] = "PLL2:2",
[DSS_CLK_SRC_PLL2_3] = "PLL2:3",
[DSS_CLK_SRC_HDMI_PLL] = "HDMI PLL",
};
static inline void dss_write_reg(struct dss_device *dss,
const struct dss_reg idx, u32 val)
{
__raw_writel(val, dss->base + idx.idx);
}
static inline u32 dss_read_reg(struct dss_device *dss, const struct dss_reg idx)
{
return __raw_readl(dss->base + idx.idx);
}
#define SR(dss, reg) \
dss->ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(dss, DSS_##reg)
#define RR(dss, reg) \
dss_write_reg(dss, DSS_##reg, dss->ctx[(DSS_##reg).idx / sizeof(u32)])
static void dss_save_context(struct dss_device *dss)
{
DSSDBG("dss_save_context\n");
SR(dss, CONTROL);
if (dss->feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
SR(dss, SDI_CONTROL);
SR(dss, PLL_CONTROL);
}
dss->ctx_valid = true;
DSSDBG("context saved\n");
}
static void dss_restor
|