18097Sjkh// SPDX-License-Identifier: GPL-2.0 28097Sjkh/* 38097Sjkh * Copyright (C) STMicroelectronics SA 2014 48097Sjkh * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. 58097Sjkh */ 68097Sjkh#include <linux/seq_file.h> 750479Speter 88097Sjkh#include <drm/drm_debugfs.h> 98097Sjkh#include <drm/drm_file.h> 108097Sjkh#include <drm/drm_print.h> 118097Sjkh 128097Sjkh#include "sti_plane.h" 138097Sjkh#include "sti_vid.h" 148097Sjkh#include "sti_vtg.h" 158097Sjkh 168881Srgrimes/* Registers */ 178881Srgrimes#define VID_CTL 0x00 188097Sjkh#define VID_ALP 0x04 198097Sjkh#define VID_CLF 0x08 208097Sjkh#define VID_VPO 0x0C 218097Sjkh#define VID_VPS 0x10 228097Sjkh#define VID_KEY1 0x28 238097Sjkh#define VID_KEY2 0x2C 248097Sjkh#define VID_MPR0 0x30 258097Sjkh#define VID_MPR1 0x34 268097Sjkh#define VID_MPR2 0x38 278097Sjkh#define VID_MPR3 0x3C 288097Sjkh#define VID_MST 0x68 298097Sjkh#define VID_BC 0x70 308097Sjkh#define VID_TINT 0x74 318097Sjkh#define VID_CSAT 0x78 328097Sjkh 338097Sjkh/* Registers values */ 348097Sjkh#define VID_CTL_IGNORE (BIT(31) | BIT(30)) 358097Sjkh#define VID_CTL_PSI_ENABLE (BIT(2) | BIT(1) | BIT(0)) 368097Sjkh#define VID_ALP_OPAQUE 0x00000080 378097Sjkh#define VID_BC_DFLT 0x00008000 388097Sjkh#define VID_TINT_DFLT 0x00000000 398097Sjkh#define VID_CSAT_DFLT 0x00000080 4021243Sjkh/* YCbCr to RGB BT709: 4121243Sjkh * R = Y+1.5391Cr 4237735Sjkh * G = Y-0.4590Cr-0.1826Cb 4325052Sjkh * B = Y+1.8125Cb */ 448097Sjkh#define VID_MPR0_BT709 0x0A800000 458097Sjkh#define VID_MPR1_BT709 0x0AC50000 468097Sjkh#define VID_MPR2_BT709 0x07150545 478097Sjkh#define VID_MPR3_BT709 0x00000AE8 488097Sjkh/* YCbCr to RGB BT709: 4921243Sjkh * R = Y+1.3711Cr 5021243Sjkh * G = Y-0.6992Cr-0.3359Cb 5121243Sjkh * B = Y+1.7344Cb 528281Sjkh */ 538405Sjkh#define VID_MPR0_BT601 0x0A800000 548097Sjkh#define VID_MPR1_BT601 0x0AAF0000 558208Sjkh#define VID_MPR2_BT601 0x094E0754 568208Sjkh#define VID_MPR3_BT601 0x00000ADD 5793401Smurray 5893401Smurray#define VID_MIN_HD_HEIGHT 720 5993401Smurray 608208Sjkh#define DBGFS_DUMP(reg) seq_printf(s, "\n %-25s 0x%08X", #reg, \ 6112661Speter readl(vid->regs + reg)) 6212661Speter 638549Sjkhstatic void vid_dbg_ctl(struct seq_file *s, int val) 6417007Sjkh{ 658208Sjkh val = val >> 30; 6621806Sjkh seq_putc(s, '\t'); 6721806Sjkh 6821806Sjkh if (!(val & 1)) 698705Sjkh seq_puts(s, "NOT "); 708705Sjkh seq_puts(s, "ignored on main mixer - "); 718705Sjkh 728705Sjkh if (!(val & 2)) 738705Sjkh seq_puts(s, "NOT "); 748705Sjkh seq_puts(s, "ignored on aux mixer"); 758705Sjkh} 768705Sjkh 7712661Speterstatic void vid_dbg_vpo(struct seq_file *s, int val) 788208Sjkh{ 7912661Speter seq_printf(s, "\txdo:%4d\tydo:%4d", val & 0x0FFF, (val >> 16) & 0x0FFF); 8015788Sjkh} 8115788Sjkh 8215788Sjkhstatic void vid_dbg_vps(struct seq_file *s, int val) 8315788Sjkh{ 8415788Sjkh seq_printf(s, "\txds:%4d\tyds:%4d", val & 0x0FFF, (val >> 16) & 0x0FFF); 8515788Sjkh} 868549Sjkh 8712661Speterstatic void vid_dbg_mst(struct seq_file *s, int val) 8812661Speter{ 8912661Speter if (val & 1) 9012661Speter seq_puts(s, "\tBUFFER UNDERFLOW!"); 9112661Speter} 9212661Speter 9312661Speterstatic int vid_dbg_show(struct seq_file *s, void *arg) 9446117Sjkh{ 9512661Speter struct drm_info_node *node = s->private; 9626456Sjkh struct sti_vid *vid = (struct sti_vid *)node->info_ent->data; 9725473Spst 9857613Sjkh seq_printf(s, "VID: (vaddr= 0x%p)", vid->regs); 9925473Spst 10025473Spst DBGFS_DUMP(VID_CTL); 10125473Spst vid_dbg_ctl(s, readl(vid->regs + VID_CTL)); 10225473Spst DBGFS_DUMP(VID_ALP); 10325473Spst DBGFS_DUMP(VID_CLF); 10412661Speter DBGFS_DUMP(VID_VPO); 10514763Sjkh vid_dbg_vpo(s, readl(vid->regs + VID_VPO)); 10612661Speter DBGFS_DUMP(VID_VPS); 10729539Spst vid_dbg_vps(s, readl(vid->regs + VID_VPS)); 10829539Spst DBGFS_DUMP(VID_KEY1); 10960657Sobrien DBGFS_DUMP(VID_KEY2); 11016410Sjkh DBGFS_DUMP(VID_MPR0); 11112661Speter DBGFS_DUMP(VID_MPR1); 11243688Sjkh DBGFS_DUMP(VID_MPR2); 11316462Sjkh DBGFS_DUMP(VID_MPR3); 11412661Speter DBGFS_DUMP(VID_MST); 11512661Speter vid_dbg_mst(s, readl(vid->regs + VID_MST)); 11616410Sjkh DBGFS_DUMP(VID_BC); 11755392Sjkh DBGFS_DUMP(VID_TINT); 11866369Sjkh DBGFS_DUMP(VID_CSAT); 11955392Sjkh seq_putc(s, '\n'); 12055392Sjkh return 0; 12155392Sjkh} 12212661Speter 12312661Speterstatic struct drm_info_list vid_debugfs_files[] = { 12412661Speter { "vid", vid_dbg_show, 0, NULL }, 12512661Speter}; 12624038Sjkh 12717034Sjkhvoid vid_debugfs_init(struct sti_vid *vid, struct drm_minor *minor) 12812661Speter{ 12963118Sume unsigned int i; 13063118Sume 13129539Spst for (i = 0; i < ARRAY_SIZE(vid_debugfs_files); i++) 13212661Speter vid_debugfs_files[i].data = vid; 13312661Speter 13448624Sjkh drm_debugfs_create_files(vid_debugfs_files, 13512661Speter ARRAY_SIZE(vid_debugfs_files), 13621855Sjkh minor->debugfs_root, minor); 13734150Sjkh} 13859088Smurray 13934150Sjkhvoid sti_vid_commit(struct sti_vid *vid, 14034150Sjkh struct drm_plane_state *state) 14112661Speter{ 14229539Spst struct drm_crtc *crtc = state->crtc; 14312661Speter struct drm_display_mode *mode = &crtc->mode; 14426514Sjkh int dst_x = state->crtc_x; 14549441Sphk int dst_y = state->crtc_y; 14612661Speter int dst_w = clamp_val(state->crtc_w, 0, mode->hdisplay - dst_x); 14716410Sjkh int dst_h = clamp_val(state->crtc_h, 0, mode->vdisplay - dst_y); 14843685Sjkh int src_h = state->src_h >> 16; 14926010Sjkh u32 val, ydo, xdo, yds, xds; 15012661Speter 15126795Sjkh /* Input / output size 15274177Sjkh * Align to upper even value */ 15326717Sjkh dst_w = ALIGN(dst_w, 2); 15437735Sjkh dst_h = ALIGN(dst_h, 2); 15587583Sdillon 15687557Sdillon /* Unmask */ 15726456Sjkh val = readl(vid->regs + VID_CTL); 15816828Sjkh val &= ~VID_CTL_IGNORE; 15929539Spst writel(val, vid->regs + VID_CTL); 16029539Spst 16126456Sjkh ydo = sti_vtg_get_line_number(*mode, dst_y); 16216366Sjkh yds = sti_vtg_get_line_number(*mode, dst_y + dst_h - 1); 16316366Sjkh xdo = sti_vtg_get_pixel_number(*mode, dst_x); 16412661Speter xds = sti_vtg_get_pixel_number(*mode, dst_x + dst_w - 1); 16549110Sbrian 16649110Sbrian writel((ydo << 16) | xdo, vid->regs + VID_VPO); 16712661Speter writel((yds << 16) | xds, vid->regs + VID_VPS); 16812661Speter 16919385Sjkh /* Color conversion parameters */ 17025476Sjkh if (src_h >= VID_MIN_HD_HEIGHT) { 17150797Sjkh writel(VID_MPR0_BT709, vid->regs + VID_MPR0); 17216366Sjkh writel(VID_MPR1_BT709, vid->regs + VID_MPR1); 17312661Speter writel(VID_MPR2_BT709, vid->regs + VID_MPR2); 17412661Speter writel(VID_MPR3_BT709, vid->regs + VID_MPR3); 17512661Speter } else { 17650780Sjkh writel(VID_MPR0_BT601, vid->regs + VID_MPR0); 17763118Sume writel(VID_MPR1_BT601, vid->regs + VID_MPR1); 17812661Speter writel(VID_MPR2_BT601, vid->regs + VID_MPR2); 17912661Speter writel(VID_MPR3_BT601, vid->regs + VID_MPR3); 18012661Speter } 18187583Sdillon} 18287557Sdillon 18343688Sjkhvoid sti_vid_disable(struct sti_vid *vid) 18478160Solgeni{ 18579813Sache u32 val; 1869202Srgrimes 18712661Speter /* Mask */ 1889202Srgrimes val = readl(vid->regs + VID_CTL); 18912661Speter val |= VID_CTL_IGNORE; 19012661Speter writel(val, vid->regs + VID_CTL); 19157617Sjkh} 1928549Sjkh 19316208Sjkhstatic void sti_vid_init(struct sti_vid *vid) 19416294Sjkh{ 19516366Sjkh /* Enable PSI, Mask layer */ 19616208Sjkh writel(VID_CTL_PSI_ENABLE | VID_CTL_IGNORE, vid->regs + VID_CTL); 19720247Sjkh 19820569Sjkh /* Opaque */ 19916366Sjkh writel(VID_ALP_OPAQUE, vid->regs + VID_ALP); 2008208Sjkh 20176402Sjkh /* Brightness, contrast, tint, saturation */ 2028549Sjkh writel(VID_BC_DFLT, vid->regs + VID_BC); 2038549Sjkh writel(VID_TINT_DFLT, vid->regs + VID_TINT); 2048097Sjkh writel(VID_CSAT_DFLT, vid->regs + VID_CSAT); 20515242Sjkh} 20615242Sjkh 20715242Sjkhstruct sti_vid *sti_vid_create(struct device *dev, struct drm_device *drm_dev, 20815242Sjkh int id, void __iomem *baseaddr) 20915242Sjkh{ 2108097Sjkh struct sti_vid *vid; 2118097Sjkh 21215242Sjkh vid = devm_kzalloc(dev, sizeof(*vid), GFP_KERNEL); 2138174Sjkh if (!vid) { 2148174Sjkh DRM_ERROR("Failed to allocate memory for VID\n"); 2158174Sjkh return NULL; 2168174Sjkh } 21794056Smurray 21894056Smurray vid->dev = dev; 21994056Smurray vid->regs = baseaddr; 22015091Sjkh vid->id = id; 22194056Smurray 22294056Smurray sti_vid_init(vid); 22394056Smurray 2248097Sjkh return vid; 2258097Sjkh} 22625251Sjkh