brintos

brintos / linux-shallow public Read only

0
0
Text · 9.0 KiB · 7e5f146 Raw
379 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) STMicroelectronics SA 20144 * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>5 *          Fabien Dessenne <fabien.dessenne@st.com>6 *          for STMicroelectronics.7 */8 9#include <linux/moduleparam.h>10#include <linux/seq_file.h>11 12#include <drm/drm_print.h>13 14#include "sti_compositor.h"15#include "sti_mixer.h"16#include "sti_vtg.h"17 18/* Module parameter to set the background color of the mixer */19static unsigned int bkg_color = 0x000000;20MODULE_PARM_DESC(bkgcolor, "Value of the background color 0xRRGGBB");21module_param_named(bkgcolor, bkg_color, int, 0644);22 23/* regs offset */24#define GAM_MIXER_CTL      0x0025#define GAM_MIXER_BKC      0x0426#define GAM_MIXER_BCO      0x0C27#define GAM_MIXER_BCS      0x1028#define GAM_MIXER_AVO      0x2829#define GAM_MIXER_AVS      0x2C30#define GAM_MIXER_CRB      0x3431#define GAM_MIXER_ACT      0x3832#define GAM_MIXER_MBP      0x3C33#define GAM_MIXER_MX0      0x8034 35/* id for depth of CRB reg */36#define GAM_DEPTH_VID0_ID  137#define GAM_DEPTH_VID1_ID  238#define GAM_DEPTH_GDP0_ID  339#define GAM_DEPTH_GDP1_ID  440#define GAM_DEPTH_GDP2_ID  541#define GAM_DEPTH_GDP3_ID  642#define GAM_DEPTH_MASK_ID  743 44/* mask in CTL reg */45#define GAM_CTL_BACK_MASK  BIT(0)46#define GAM_CTL_VID0_MASK  BIT(1)47#define GAM_CTL_VID1_MASK  BIT(2)48#define GAM_CTL_GDP0_MASK  BIT(3)49#define GAM_CTL_GDP1_MASK  BIT(4)50#define GAM_CTL_GDP2_MASK  BIT(5)51#define GAM_CTL_GDP3_MASK  BIT(6)52#define GAM_CTL_CURSOR_MASK BIT(9)53 54const char *sti_mixer_to_str(struct sti_mixer *mixer)55{56	switch (mixer->id) {57	case STI_MIXER_MAIN:58		return "MAIN_MIXER";59	case STI_MIXER_AUX:60		return "AUX_MIXER";61	default:62		return "<UNKNOWN MIXER>";63	}64}65 66static inline u32 sti_mixer_reg_read(struct sti_mixer *mixer, u32 reg_id)67{68	return readl(mixer->regs + reg_id);69}70 71static inline void sti_mixer_reg_write(struct sti_mixer *mixer,72				       u32 reg_id, u32 val)73{74	writel(val, mixer->regs + reg_id);75}76 77#define DBGFS_DUMP(reg) seq_printf(s, "\n  %-25s 0x%08X", #reg, \78				   sti_mixer_reg_read(mixer, reg))79 80static void mixer_dbg_ctl(struct seq_file *s, int val)81{82	unsigned int i;83	int count = 0;84	char *const disp_layer[] = {"BKG", "VID0", "VID1", "GDP0",85				    "GDP1", "GDP2", "GDP3"};86 87	seq_puts(s, "\tEnabled: ");88	for (i = 0; i < 7; i++) {89		if (val & 1) {90			seq_printf(s, "%s ", disp_layer[i]);91			count++;92		}93		val = val >> 1;94	}95 96	val = val >> 2;97	if (val & 1) {98		seq_puts(s, "CURS ");99		count++;100	}101	if (!count)102		seq_puts(s, "Nothing");103}104 105static void mixer_dbg_crb(struct seq_file *s, int val)106{107	int i;108 109	seq_puts(s, "\tDepth: ");110	for (i = 0; i < GAM_MIXER_NB_DEPTH_LEVEL; i++) {111		switch (val & GAM_DEPTH_MASK_ID) {112		case GAM_DEPTH_VID0_ID:113			seq_puts(s, "VID0");114			break;115		case GAM_DEPTH_VID1_ID:116			seq_puts(s, "VID1");117			break;118		case GAM_DEPTH_GDP0_ID:119			seq_puts(s, "GDP0");120			break;121		case GAM_DEPTH_GDP1_ID:122			seq_puts(s, "GDP1");123			break;124		case GAM_DEPTH_GDP2_ID:125			seq_puts(s, "GDP2");126			break;127		case GAM_DEPTH_GDP3_ID:128			seq_puts(s, "GDP3");129			break;130		default:131			seq_puts(s, "---");132		}133 134		if (i < GAM_MIXER_NB_DEPTH_LEVEL - 1)135			seq_puts(s, " < ");136		val = val >> 3;137	}138}139 140static void mixer_dbg_mxn(struct seq_file *s, void *addr)141{142	int i;143 144	for (i = 1; i < 8; i++)145		seq_printf(s, "-0x%08X", (int)readl(addr + i * 4));146}147 148static int mixer_dbg_show(struct seq_file *s, void *arg)149{150	struct drm_info_node *node = s->private;151	struct sti_mixer *mixer = (struct sti_mixer *)node->info_ent->data;152 153	seq_printf(s, "%s: (vaddr = 0x%p)",154		   sti_mixer_to_str(mixer), mixer->regs);155 156	DBGFS_DUMP(GAM_MIXER_CTL);157	mixer_dbg_ctl(s, sti_mixer_reg_read(mixer, GAM_MIXER_CTL));158	DBGFS_DUMP(GAM_MIXER_BKC);159	DBGFS_DUMP(GAM_MIXER_BCO);160	DBGFS_DUMP(GAM_MIXER_BCS);161	DBGFS_DUMP(GAM_MIXER_AVO);162	DBGFS_DUMP(GAM_MIXER_AVS);163	DBGFS_DUMP(GAM_MIXER_CRB);164	mixer_dbg_crb(s, sti_mixer_reg_read(mixer, GAM_MIXER_CRB));165	DBGFS_DUMP(GAM_MIXER_ACT);166	DBGFS_DUMP(GAM_MIXER_MBP);167	DBGFS_DUMP(GAM_MIXER_MX0);168	mixer_dbg_mxn(s, mixer->regs + GAM_MIXER_MX0);169	seq_putc(s, '\n');170	return 0;171}172 173static struct drm_info_list mixer0_debugfs_files[] = {174	{ "mixer_main", mixer_dbg_show, 0, NULL },175};176 177static struct drm_info_list mixer1_debugfs_files[] = {178	{ "mixer_aux", mixer_dbg_show, 0, NULL },179};180 181void sti_mixer_debugfs_init(struct sti_mixer *mixer, struct drm_minor *minor)182{183	unsigned int i;184	struct drm_info_list *mixer_debugfs_files;185	int nb_files;186 187	switch (mixer->id) {188	case STI_MIXER_MAIN:189		mixer_debugfs_files = mixer0_debugfs_files;190		nb_files = ARRAY_SIZE(mixer0_debugfs_files);191		break;192	case STI_MIXER_AUX:193		mixer_debugfs_files = mixer1_debugfs_files;194		nb_files = ARRAY_SIZE(mixer1_debugfs_files);195		break;196	default:197		return;198	}199 200	for (i = 0; i < nb_files; i++)201		mixer_debugfs_files[i].data = mixer;202 203	drm_debugfs_create_files(mixer_debugfs_files,204				 nb_files,205				 minor->debugfs_root, minor);206}207 208void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable)209{210	u32 val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL);211 212	val &= ~GAM_CTL_BACK_MASK;213	val |= enable;214	sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val);215}216 217static void sti_mixer_set_background_color(struct sti_mixer *mixer,218					   unsigned int rgb)219{220	sti_mixer_reg_write(mixer, GAM_MIXER_BKC, rgb);221}222 223static void sti_mixer_set_background_area(struct sti_mixer *mixer,224					  struct drm_display_mode *mode)225{226	u32 ydo, xdo, yds, xds;227 228	ydo = sti_vtg_get_line_number(*mode, 0);229	yds = sti_vtg_get_line_number(*mode, mode->vdisplay - 1);230	xdo = sti_vtg_get_pixel_number(*mode, 0);231	xds = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1);232 233	sti_mixer_reg_write(mixer, GAM_MIXER_BCO, ydo << 16 | xdo);234	sti_mixer_reg_write(mixer, GAM_MIXER_BCS, yds << 16 | xds);235}236 237int sti_mixer_set_plane_depth(struct sti_mixer *mixer, struct sti_plane *plane)238{239	int plane_id, depth = plane->drm_plane.state->normalized_zpos;240	unsigned int i;241	u32 mask, val;242 243	switch (plane->desc) {244	case STI_GDP_0:245		plane_id = GAM_DEPTH_GDP0_ID;246		break;247	case STI_GDP_1:248		plane_id = GAM_DEPTH_GDP1_ID;249		break;250	case STI_GDP_2:251		plane_id = GAM_DEPTH_GDP2_ID;252		break;253	case STI_GDP_3:254		plane_id = GAM_DEPTH_GDP3_ID;255		break;256	case STI_HQVDP_0:257		plane_id = GAM_DEPTH_VID0_ID;258		break;259	case STI_CURSOR:260		/* no need to set depth for cursor */261		return 0;262	default:263		DRM_ERROR("Unknown plane %d\n", plane->desc);264		return 1;265	}266 267	/* Search if a previous depth was already assigned to the plane */268	val = sti_mixer_reg_read(mixer, GAM_MIXER_CRB);269	for (i = 0; i < GAM_MIXER_NB_DEPTH_LEVEL; i++) {270		mask = GAM_DEPTH_MASK_ID << (3 * i);271		if ((val & mask) == plane_id << (3 * i))272			break;273	}274 275	mask |= GAM_DEPTH_MASK_ID << (3 * depth);276	plane_id = plane_id << (3 * depth);277 278	DRM_DEBUG_DRIVER("%s %s depth=%d\n", sti_mixer_to_str(mixer),279			 sti_plane_to_str(plane), depth);280	dev_dbg(mixer->dev, "GAM_MIXER_CRB val 0x%x mask 0x%x\n",281		plane_id, mask);282 283	val &= ~mask;284	val |= plane_id;285	sti_mixer_reg_write(mixer, GAM_MIXER_CRB, val);286 287	dev_dbg(mixer->dev, "Read GAM_MIXER_CRB 0x%x\n",288		sti_mixer_reg_read(mixer, GAM_MIXER_CRB));289	return 0;290}291 292int sti_mixer_active_video_area(struct sti_mixer *mixer,293				struct drm_display_mode *mode)294{295	u32 ydo, xdo, yds, xds;296 297	ydo = sti_vtg_get_line_number(*mode, 0);298	yds = sti_vtg_get_line_number(*mode, mode->vdisplay - 1);299	xdo = sti_vtg_get_pixel_number(*mode, 0);300	xds = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1);301 302	DRM_DEBUG_DRIVER("%s active video area xdo:%d ydo:%d xds:%d yds:%d\n",303			 sti_mixer_to_str(mixer), xdo, ydo, xds, yds);304	sti_mixer_reg_write(mixer, GAM_MIXER_AVO, ydo << 16 | xdo);305	sti_mixer_reg_write(mixer, GAM_MIXER_AVS, yds << 16 | xds);306 307	sti_mixer_set_background_color(mixer, bkg_color);308 309	sti_mixer_set_background_area(mixer, mode);310	sti_mixer_set_background_status(mixer, true);311	return 0;312}313 314static u32 sti_mixer_get_plane_mask(struct sti_plane *plane)315{316	switch (plane->desc) {317	case STI_BACK:318		return GAM_CTL_BACK_MASK;319	case STI_GDP_0:320		return GAM_CTL_GDP0_MASK;321	case STI_GDP_1:322		return GAM_CTL_GDP1_MASK;323	case STI_GDP_2:324		return GAM_CTL_GDP2_MASK;325	case STI_GDP_3:326		return GAM_CTL_GDP3_MASK;327	case STI_HQVDP_0:328		return GAM_CTL_VID0_MASK;329	case STI_CURSOR:330		return GAM_CTL_CURSOR_MASK;331	default:332		return 0;333	}334}335 336int sti_mixer_set_plane_status(struct sti_mixer *mixer,337			       struct sti_plane *plane, bool status)338{339	u32 mask, val;340 341	DRM_DEBUG_DRIVER("%s %s %s\n", status ? "enable" : "disable",342			 sti_mixer_to_str(mixer), sti_plane_to_str(plane));343 344	mask = sti_mixer_get_plane_mask(plane);345	if (!mask) {346		DRM_ERROR("Can't find layer mask\n");347		return -EINVAL;348	}349 350	val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL);351	val &= ~mask;352	val |= status ? mask : 0;353	sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val);354 355	return 0;356}357 358struct sti_mixer *sti_mixer_create(struct device *dev,359				   struct drm_device *drm_dev,360				   int id,361				   void __iomem *baseaddr)362{363	struct sti_mixer *mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);364 365	dev_dbg(dev, "%s\n", __func__);366	if (!mixer) {367		DRM_ERROR("Failed to allocated memory for mixer\n");368		return NULL;369	}370	mixer->regs = baseaddr;371	mixer->dev = dev;372	mixer->id = id;373 374	DRM_DEBUG_DRIVER("%s created. Regs=%p\n",375			 sti_mixer_to_str(mixer), mixer->regs);376 377	return mixer;378}379