0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/moduleparam.h>
0010 #include <linux/seq_file.h>
0011
0012 #include <drm/drm_print.h>
0013
0014 #include "sti_compositor.h"
0015 #include "sti_mixer.h"
0016 #include "sti_vtg.h"
0017
0018
0019 static unsigned int bkg_color = 0x000000;
0020 MODULE_PARM_DESC(bkgcolor, "Value of the background color 0xRRGGBB");
0021 module_param_named(bkgcolor, bkg_color, int, 0644);
0022
0023
0024 #define GAM_MIXER_CTL 0x00
0025 #define GAM_MIXER_BKC 0x04
0026 #define GAM_MIXER_BCO 0x0C
0027 #define GAM_MIXER_BCS 0x10
0028 #define GAM_MIXER_AVO 0x28
0029 #define GAM_MIXER_AVS 0x2C
0030 #define GAM_MIXER_CRB 0x34
0031 #define GAM_MIXER_ACT 0x38
0032 #define GAM_MIXER_MBP 0x3C
0033 #define GAM_MIXER_MX0 0x80
0034
0035
0036 #define GAM_DEPTH_VID0_ID 1
0037 #define GAM_DEPTH_VID1_ID 2
0038 #define GAM_DEPTH_GDP0_ID 3
0039 #define GAM_DEPTH_GDP1_ID 4
0040 #define GAM_DEPTH_GDP2_ID 5
0041 #define GAM_DEPTH_GDP3_ID 6
0042 #define GAM_DEPTH_MASK_ID 7
0043
0044
0045 #define GAM_CTL_BACK_MASK BIT(0)
0046 #define GAM_CTL_VID0_MASK BIT(1)
0047 #define GAM_CTL_VID1_MASK BIT(2)
0048 #define GAM_CTL_GDP0_MASK BIT(3)
0049 #define GAM_CTL_GDP1_MASK BIT(4)
0050 #define GAM_CTL_GDP2_MASK BIT(5)
0051 #define GAM_CTL_GDP3_MASK BIT(6)
0052 #define GAM_CTL_CURSOR_MASK BIT(9)
0053
0054 const char *sti_mixer_to_str(struct sti_mixer *mixer)
0055 {
0056 switch (mixer->id) {
0057 case STI_MIXER_MAIN:
0058 return "MAIN_MIXER";
0059 case STI_MIXER_AUX:
0060 return "AUX_MIXER";
0061 default:
0062 return "<UNKNOWN MIXER>";
0063 }
0064 }
0065
0066 static inline u32 sti_mixer_reg_read(struct sti_mixer *mixer, u32 reg_id)
0067 {
0068 return readl(mixer->regs + reg_id);
0069 }
0070
0071 static inline void sti_mixer_reg_write(struct sti_mixer *mixer,
0072 u32 reg_id, u32 val)
0073 {
0074 writel(val, mixer->regs + reg_id);
0075 }
0076
0077 #define DBGFS_DUMP(reg) seq_printf(s, "\n %-25s 0x%08X", #reg, \
0078 sti_mixer_reg_read(mixer, reg))
0079
0080 static void mixer_dbg_ctl(struct seq_file *s, int val)
0081 {
0082 unsigned int i;
0083 int count = 0;
0084 char *const disp_layer[] = {"BKG", "VID0", "VID1", "GDP0",
0085 "GDP1", "GDP2", "GDP3"};
0086
0087 seq_puts(s, "\tEnabled: ");
0088 for (i = 0; i < 7; i++) {
0089 if (val & 1) {
0090 seq_printf(s, "%s ", disp_layer[i]);
0091 count++;
0092 }
0093 val = val >> 1;
0094 }
0095
0096 val = val >> 2;
0097 if (val & 1) {
0098 seq_puts(s, "CURS ");
0099 count++;
0100 }
0101 if (!count)
0102 seq_puts(s, "Nothing");
0103 }
0104
0105 static void mixer_dbg_crb(struct seq_file *s, int val)
0106 {
0107 int i;
0108
0109 seq_puts(s, "\tDepth: ");
0110 for (i = 0; i < GAM_MIXER_NB_DEPTH_LEVEL; i++) {
0111 switch (val & GAM_DEPTH_MASK_ID) {
0112 case GAM_DEPTH_VID0_ID:
0113 seq_puts(s, "VID0");
0114 break;
0115 case GAM_DEPTH_VID1_ID:
0116 seq_puts(s, "VID1");
0117 break;
0118 case GAM_DEPTH_GDP0_ID:
0119 seq_puts(s, "GDP0");
0120 break;
0121 case GAM_DEPTH_GDP1_ID:
0122 seq_puts(s, "GDP1");
0123 break;
0124 case GAM_DEPTH_GDP2_ID:
0125 seq_puts(s, "GDP2");
0126 break;
0127 case GAM_DEPTH_GDP3_ID:
0128 seq_puts(s, "GDP3");
0129 break;
0130 default:
0131 seq_puts(s, "---");
0132 }
0133
0134 if (i < GAM_MIXER_NB_DEPTH_LEVEL - 1)
0135 seq_puts(s, " < ");
0136 val = val >> 3;
0137 }
0138 }
0139
0140 static void mixer_dbg_mxn(struct seq_file *s, void *addr)
0141 {
0142 int i;
0143
0144 for (i = 1; i < 8; i++)
0145 seq_printf(s, "-0x%08X", (int)readl(addr + i * 4));
0146 }
0147
0148 static int mixer_dbg_show(struct seq_file *s, void *arg)
0149 {
0150 struct drm_info_node *node = s->private;
0151 struct sti_mixer *mixer = (struct sti_mixer *)node->info_ent->data;
0152
0153 seq_printf(s, "%s: (vaddr = 0x%p)",
0154 sti_mixer_to_str(mixer), mixer->regs);
0155
0156 DBGFS_DUMP(GAM_MIXER_CTL);
0157 mixer_dbg_ctl(s, sti_mixer_reg_read(mixer, GAM_MIXER_CTL));
0158 DBGFS_DUMP(GAM_MIXER_BKC);
0159 DBGFS_DUMP(GAM_MIXER_BCO);
0160 DBGFS_DUMP(GAM_MIXER_BCS);
0161 DBGFS_DUMP(GAM_MIXER_AVO);
0162 DBGFS_DUMP(GAM_MIXER_AVS);
0163 DBGFS_DUMP(GAM_MIXER_CRB);
0164 mixer_dbg_crb(s, sti_mixer_reg_read(mixer, GAM_MIXER_CRB));
0165 DBGFS_DUMP(GAM_MIXER_ACT);
0166 DBGFS_DUMP(GAM_MIXER_MBP);
0167 DBGFS_DUMP(GAM_MIXER_MX0);
0168 mixer_dbg_mxn(s, mixer->regs + GAM_MIXER_MX0);
0169 seq_putc(s, '\n');
0170 return 0;
0171 }
0172
0173 static struct drm_info_list mixer0_debugfs_files[] = {
0174 { "mixer_main", mixer_dbg_show, 0, NULL },
0175 };
0176
0177 static struct drm_info_list mixer1_debugfs_files[] = {
0178 { "mixer_aux", mixer_dbg_show, 0, NULL },
0179 };
0180
0181 void sti_mixer_debugfs_init(struct sti_mixer *mixer, struct drm_minor *minor)
0182 {
0183 unsigned int i;
0184 struct drm_info_list *mixer_debugfs_files;
0185 int nb_files;
0186
0187 switch (mixer->id) {
0188 case STI_MIXER_MAIN:
0189 mixer_debugfs_files = mixer0_debugfs_files;
0190 nb_files = ARRAY_SIZE(mixer0_debugfs_files);
0191 break;
0192 case STI_MIXER_AUX:
0193 mixer_debugfs_files = mixer1_debugfs_files;
0194 nb_files = ARRAY_SIZE(mixer1_debugfs_files);
0195 break;
0196 default:
0197 return;
0198 }
0199
0200 for (i = 0; i < nb_files; i++)
0201 mixer_debugfs_files[i].data = mixer;
0202
0203 drm_debugfs_create_files(mixer_debugfs_files,
0204 nb_files,
0205 minor->debugfs_root, minor);
0206 }
0207
0208 void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable)
0209 {
0210 u32 val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL);
0211
0212 val &= ~GAM_CTL_BACK_MASK;
0213 val |= enable;
0214 sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val);
0215 }
0216
0217 static void sti_mixer_set_background_color(struct sti_mixer *mixer,
0218 unsigned int rgb)
0219 {
0220 sti_mixer_reg_write(mixer, GAM_MIXER_BKC, rgb);
0221 }
0222
0223 static void sti_mixer_set_background_area(struct sti_mixer *mixer,
0224 struct drm_display_mode *mode)
0225 {
0226 u32 ydo, xdo, yds, xds;
0227
0228 ydo = sti_vtg_get_line_number(*mode, 0);
0229 yds = sti_vtg_get_line_number(*mode, mode->vdisplay - 1);
0230 xdo = sti_vtg_get_pixel_number(*mode, 0);
0231 xds = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1);
0232
0233 sti_mixer_reg_write(mixer, GAM_MIXER_BCO, ydo << 16 | xdo);
0234 sti_mixer_reg_write(mixer, GAM_MIXER_BCS, yds << 16 | xds);
0235 }
0236
0237 int sti_mixer_set_plane_depth(struct sti_mixer *mixer, struct sti_plane *plane)
0238 {
0239 int plane_id, depth = plane->drm_plane.state->normalized_zpos;
0240 unsigned int i;
0241 u32 mask, val;
0242
0243 switch (plane->desc) {
0244 case STI_GDP_0:
0245 plane_id = GAM_DEPTH_GDP0_ID;
0246 break;
0247 case STI_GDP_1:
0248 plane_id = GAM_DEPTH_GDP1_ID;
0249 break;
0250 case STI_GDP_2:
0251 plane_id = GAM_DEPTH_GDP2_ID;
0252 break;
0253 case STI_GDP_3:
0254 plane_id = GAM_DEPTH_GDP3_ID;
0255 break;
0256 case STI_HQVDP_0:
0257 plane_id = GAM_DEPTH_VID0_ID;
0258 break;
0259 case STI_CURSOR:
0260
0261 return 0;
0262 default:
0263 DRM_ERROR("Unknown plane %d\n", plane->desc);
0264 return 1;
0265 }
0266
0267
0268 val = sti_mixer_reg_read(mixer, GAM_MIXER_CRB);
0269 for (i = 0; i < GAM_MIXER_NB_DEPTH_LEVEL; i++) {
0270 mask = GAM_DEPTH_MASK_ID << (3 * i);
0271 if ((val & mask) == plane_id << (3 * i))
0272 break;
0273 }
0274
0275 mask |= GAM_DEPTH_MASK_ID << (3 * depth);
0276 plane_id = plane_id << (3 * depth);
0277
0278 DRM_DEBUG_DRIVER("%s %s depth=%d\n", sti_mixer_to_str(mixer),
0279 sti_plane_to_str(plane), depth);
0280 dev_dbg(mixer->dev, "GAM_MIXER_CRB val 0x%x mask 0x%x\n",
0281 plane_id, mask);
0282
0283 val &= ~mask;
0284 val |= plane_id;
0285 sti_mixer_reg_write(mixer, GAM_MIXER_CRB, val);
0286
0287 dev_dbg(mixer->dev, "Read GAM_MIXER_CRB 0x%x\n",
0288 sti_mixer_reg_read(mixer, GAM_MIXER_CRB));
0289 return 0;
0290 }
0291
0292 int sti_mixer_active_video_area(struct sti_mixer *mixer,
0293 struct drm_display_mode *mode)
0294 {
0295 u32 ydo, xdo, yds, xds;
0296
0297 ydo = sti_vtg_get_line_number(*mode, 0);
0298 yds = sti_vtg_get_line_number(*mode, mode->vdisplay - 1);
0299 xdo = sti_vtg_get_pixel_number(*mode, 0);
0300 xds = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1);
0301
0302 DRM_DEBUG_DRIVER("%s active video area xdo:%d ydo:%d xds:%d yds:%d\n",
0303 sti_mixer_to_str(mixer), xdo, ydo, xds, yds);
0304 sti_mixer_reg_write(mixer, GAM_MIXER_AVO, ydo << 16 | xdo);
0305 sti_mixer_reg_write(mixer, GAM_MIXER_AVS, yds << 16 | xds);
0306
0307 sti_mixer_set_background_color(mixer, bkg_color);
0308
0309 sti_mixer_set_background_area(mixer, mode);
0310 sti_mixer_set_background_status(mixer, true);
0311 return 0;
0312 }
0313
0314 static u32 sti_mixer_get_plane_mask(struct sti_plane *plane)
0315 {
0316 switch (plane->desc) {
0317 case STI_BACK:
0318 return GAM_CTL_BACK_MASK;
0319 case STI_GDP_0:
0320 return GAM_CTL_GDP0_MASK;
0321 case STI_GDP_1:
0322 return GAM_CTL_GDP1_MASK;
0323 case STI_GDP_2:
0324 return GAM_CTL_GDP2_MASK;
0325 case STI_GDP_3:
0326 return GAM_CTL_GDP3_MASK;
0327 case STI_HQVDP_0:
0328 return GAM_CTL_VID0_MASK;
0329 case STI_CURSOR:
0330 return GAM_CTL_CURSOR_MASK;
0331 default:
0332 return 0;
0333 }
0334 }
0335
0336 int sti_mixer_set_plane_status(struct sti_mixer *mixer,
0337 struct sti_plane *plane, bool status)
0338 {
0339 u32 mask, val;
0340
0341 DRM_DEBUG_DRIVER("%s %s %s\n", status ? "enable" : "disable",
0342 sti_mixer_to_str(mixer), sti_plane_to_str(plane));
0343
0344 mask = sti_mixer_get_plane_mask(plane);
0345 if (!mask) {
0346 DRM_ERROR("Can't find layer mask\n");
0347 return -EINVAL;
0348 }
0349
0350 val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL);
0351 val &= ~mask;
0352 val |= status ? mask : 0;
0353 sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val);
0354
0355 return 0;
0356 }
0357
0358 struct sti_mixer *sti_mixer_create(struct device *dev,
0359 struct drm_device *drm_dev,
0360 int id,
0361 void __iomem *baseaddr)
0362 {
0363 struct sti_mixer *mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
0364
0365 dev_dbg(dev, "%s\n", __func__);
0366 if (!mixer) {
0367 DRM_ERROR("Failed to allocated memory for mixer\n");
0368 return NULL;
0369 }
0370 mixer->regs = baseaddr;
0371 mixer->dev = dev;
0372 mixer->id = id;
0373
0374 DRM_DEBUG_DRIVER("%s created. Regs=%p\n",
0375 sti_mixer_to_str(mixer), mixer->regs);
0376
0377 return mixer;
0378 }