sh_mobile_lcdcfb.c revision 0c75c4e073a8ec35bfd6c8adcceb2b896f2063e2
1cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm/* 2cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * SuperH Mobile LCDC Framebuffer 3cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * 4cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * Copyright (c) 2008 Magnus Damm 5cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * 6cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * This file is subject to the terms and conditions of the GNU General Public 7cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * License. See the file "COPYING" in the main directory of this archive 8cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * for more details. 9cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm */ 10cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 11f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/atomic.h> 12f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/backlight.h> 13cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm#include <linux/clk.h> 14f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/console.h> 15c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#include <linux/ctype.h> 16cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm#include <linux/dma-mapping.h> 17f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/delay.h> 18f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/gpio.h> 19f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/init.h> 208564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm#include <linux/interrupt.h> 2140331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy#include <linux/ioctl.h> 22f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/kernel.h> 23f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/mm.h> 24355b200bacdb6017669cdc5bc9e7b1037aac42a2Paul Gortmaker#include <linux/module.h> 25f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/platform_device.h> 26f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/pm_runtime.h> 27f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/slab.h> 28f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/videodev2.h> 29f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/vmalloc.h> 30f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 31225c9a8d1da274bf23efec43ec28b1c9e45e12f8Paul Mundt#include <video/sh_mobile_lcdc.h> 328a20974f0370fe1b924704399e7ba327d894ef72Laurent Pinchart#include <video/sh_mobile_meram.h> 33cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 346de9edd5bde0cdfea12e9948690e53ec669c3018Guennadi Liakhovetski#include "sh_mobile_lcdcfb.h" 356de9edd5bde0cdfea12e9948690e53ec669c3018Guennadi Liakhovetski 36c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart/* ---------------------------------------------------------------------------- 37c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * Overlay register definitions 38c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 39c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 40c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBCR 0xb00 41c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBCR_UPC(n) (1 << ((n) + 16)) 42c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBCR_UPF(n) (1 << ((n) + 8)) 43c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBCR_UPD(n) (1 << ((n) + 0)) 44c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSIFR(n) (0xb20 + (n) * 0x20 + 0x00) 45c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_EN (1 << 31) 46c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_VS (1 << 29) 47c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_BRSEL (1 << 28) 48c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_MX (1 << 27) 49c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_MY (1 << 26) 50c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CV3 (3 << 24) 51c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CV2 (2 << 24) 52c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CV1 (1 << 24) 53c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CV0 (0 << 24) 54c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CV_MASK (3 << 24) 55c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_LAY_MASK (0xff << 16) 56c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_LAY_SHIFT 16 57c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_ROP3_MASK (0xff << 16) 58c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_ROP3_SHIFT 16 59c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_AL_PL8 (3 << 14) 60c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_AL_PL1 (2 << 14) 61c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_AL_PK (1 << 14) 62c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_AL_1 (0 << 14) 63c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_AL_MASK (3 << 14) 64c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_SWPL (1 << 10) 65c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_SWPW (1 << 9) 66c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_SWPB (1 << 8) 67c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_RY (1 << 7) 68c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CHRR_420 (2 << 0) 69c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CHRR_422 (1 << 0) 70c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CHRR_444 (0 << 0) 71c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_RPKF_ARGB32 (0x00 << 0) 72c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_RPKF_RGB16 (0x03 << 0) 73c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_RPKF_RGB24 (0x0b << 0) 74c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_RPKF_MASK (0x1f << 0) 75c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSSZR(n) (0xb20 + (n) * 0x20 + 0x04) 76c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSSZR_BVSS_MASK (0xfff << 16) 77c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSSZR_BVSS_SHIFT 16 78c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSSZR_BHSS_MASK (0xfff << 0) 79c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSSZR_BHSS_SHIFT 0 80c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBLOCR(n) (0xb20 + (n) * 0x20 + 0x08) 81c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBLOCR_CVLC_MASK (0xfff << 16) 82c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBLOCR_CVLC_SHIFT 16 83c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBLOCR_CHLC_MASK (0xfff << 0) 84c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBLOCR_CHLC_SHIFT 0 85c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSMWR(n) (0xb20 + (n) * 0x20 + 0x0c) 86c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSMWR_BSMWA_MASK (0xffff << 16) 87c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSMWR_BSMWA_SHIFT 16 88c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSMWR_BSMW_MASK (0xffff << 0) 89c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSMWR_BSMW_SHIFT 0 90c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSAYR(n) (0xb20 + (n) * 0x20 + 0x10) 91c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1A_MASK (0xff << 24) 92c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1A_SHIFT 24 93c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1R_MASK (0xff << 16) 94c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1R_SHIFT 16 95c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1G_MASK (0xff << 8) 96c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1G_SHIFT 8 97c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1B_MASK (0xff << 0) 98c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1B_SHIFT 0 99c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSACR(n) (0xb20 + (n) * 0x20 + 0x14) 100c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2A_MASK (0xff << 24) 101c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2A_SHIFT 24 102c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2R_MASK (0xff << 16) 103c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2R_SHIFT 16 104c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2G_MASK (0xff << 8) 105c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2G_SHIFT 8 106c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2B_MASK (0xff << 0) 107c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2B_SHIFT 0 108c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSAAR(n) (0xb20 + (n) * 0x20 + 0x18) 109c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_AP_MASK (0xff << 24) 110c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_AP_SHIFT 24 111c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_R_MASK (0xff << 16) 112c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_R_SHIFT 16 113c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_GY_MASK (0xff << 8) 114c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_GY_SHIFT 8 115c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_B_MASK (0xff << 0) 116c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_B_SHIFT 0 117c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBPPCR(n) (0xb20 + (n) * 0x20 + 0x1c) 118c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_AP_MASK (0xff << 24) 119c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_AP_SHIFT 24 120c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_R_MASK (0xff << 16) 121c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_R_SHIFT 16 122c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_GY_MASK (0xff << 8) 123c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_GY_SHIFT 8 124c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_B_MASK (0xff << 0) 125c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_B_SHIFT 0 126c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBBGCL(n) (0xb10 + (n) * 0x04) 127c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGA_MASK (0xff << 24) 128c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGA_SHIFT 24 129c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGR_MASK (0xff << 16) 130c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGR_SHIFT 16 131c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGG_MASK (0xff << 8) 132c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGG_SHIFT 8 133c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGB_MASK (0xff << 0) 134c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGB_SHIFT 0 135c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 136a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy#define SIDE_B_OFFSET 0x1000 137a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy#define MIRROR_OFFSET 0x2000 138cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 139d2ecbab5960d9814a269d36723647d6ef391ba8fGuennadi Liakhovetski#define MAX_XRES 1920 140d2ecbab5960d9814a269d36723647d6ef391ba8fGuennadi Liakhovetski#define MAX_YRES 1080 141cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 142c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartenum sh_mobile_lcdc_overlay_mode { 143c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart LCDC_OVERLAY_BLEND, 144c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart LCDC_OVERLAY_ROP3, 145c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 146c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 147c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart/* 148c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * struct sh_mobile_lcdc_overlay - LCDC display overlay 149c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * 150c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @channel: LCDC channel this overlay belongs to 151c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @cfg: Overlay configuration 152c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @info: Frame buffer device 153c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @index: Overlay index (0-3) 154c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @base: Overlay registers base address 155c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @enabled: True if the overlay is enabled 156c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @mode: Overlay blending mode (alpha blend or ROP3) 157c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @alpha: Global alpha blending value (0-255, for alpha blending mode) 158c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @rop3: Raster operation (for ROP3 mode) 159c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @fb_mem: Frame buffer virtual memory address 160c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @fb_size: Frame buffer size in bytes 161c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @dma_handle: Frame buffer DMA address 162c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @base_addr_y: Overlay base address (RGB or luma component) 163c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @base_addr_c: Overlay base address (chroma component) 164c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @pan_offset: Current pan offset in bytes 165c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @format: Current pixelf format 166c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @xres: Horizontal visible resolution 167c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @xres_virtual: Horizontal total resolution 168c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @yres: Vertical visible resolution 169c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @yres_virtual: Vertical total resolution 170c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @pitch: Overlay line pitch 171c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @pos_x: Horizontal overlay position 172c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @pos_y: Vertical overlay position 173c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 174c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstruct sh_mobile_lcdc_overlay { 175c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_chan *channel; 176c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 177c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const struct sh_mobile_lcdc_overlay_cfg *cfg; 178c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info; 179c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 180c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int index; 181c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base; 182c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 183c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart bool enabled; 184c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart enum sh_mobile_lcdc_overlay_mode mode; 185c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int alpha; 186c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int rop3; 187c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 188c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart void *fb_mem; 189c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long fb_size; 190c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 191c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dma_addr_t dma_handle; 192c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base_addr_y; 193c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base_addr_c; 194c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long pan_offset; 195c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 196c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const struct sh_mobile_lcdc_format_info *format; 197c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int xres; 198c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int xres_virtual; 199c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int yres; 200c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int yres_virtual; 201c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int pitch; 202c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int pos_x; 203c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int pos_y; 204c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 205c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 206f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstruct sh_mobile_lcdc_priv { 207f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart void __iomem *base; 208f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart int irq; 209f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart atomic_t hw_usecnt; 210f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart struct device *dev; 211f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart struct clk *dot_clk; 212f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart unsigned long lddckr; 213c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 214f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart struct sh_mobile_lcdc_chan ch[2]; 215c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay overlays[4]; 216c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 217f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart struct notifier_block notifier; 218f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart int started; 219f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart int forced_fourcc; /* 2 channel LCDC must share fourcc setting */ 220f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart struct sh_mobile_meram_info *meram_dev; 221f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart}; 222f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 223f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 224f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Registers access 225f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 226f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2270246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Dammstatic unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 228cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDCKPAT1R] = 0x400, 229cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDCKPAT2R] = 0x404, 230cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT1R] = 0x418, 231cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT2R] = 0x41c, 232cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT3R] = 0x420, 233cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDFR] = 0x424, 234cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDSM1R] = 0x428, 2358564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm [LDSM2R] = 0x42c, 236cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDSA1R] = 0x430, 23753b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia [LDSA2R] = 0x434, 238cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMLSR] = 0x438, 239cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDHCNR] = 0x448, 240cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDHSYNR] = 0x44c, 241cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDVLNR] = 0x450, 242cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDVSYNR] = 0x454, 243cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDPMR] = 0x460, 2446011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski [LDHAJR] = 0x4a0, 245cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 246cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2470246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Dammstatic unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { 248cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDCKPAT1R] = 0x408, 249cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDCKPAT2R] = 0x40c, 250cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT1R] = 0x600, 251cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT2R] = 0x604, 252cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT3R] = 0x608, 253cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDFR] = 0x60c, 254cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDSM1R] = 0x610, 2558564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm [LDSM2R] = 0x614, 256cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDSA1R] = 0x618, 257cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMLSR] = 0x620, 258cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDHCNR] = 0x624, 259cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDHSYNR] = 0x628, 260cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDVLNR] = 0x62c, 261cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDVSYNR] = 0x630, 262cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDPMR] = 0x63c, 263cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 264cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 265a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthystatic bool banked(int reg_nr) 266a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy{ 267a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy switch (reg_nr) { 268a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDMT1R: 269a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDMT2R: 270a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDMT3R: 271a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDDFR: 272a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDSM1R: 273a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDSA1R: 27453b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia case LDSA2R: 275a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDMLSR: 276a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDHCNR: 277a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDHSYNR: 278a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDVLNR: 279a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDVSYNR: 280a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy return true; 281a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy } 282a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy return false; 283a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy} 284a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy 285f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan) 286f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 287b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart return chan->cfg->chan == LCDC_CHAN_SUBLCD; 288f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 289f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 290cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan, 291cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int reg_nr, unsigned long data) 292cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 293cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]); 294a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy if (banked(reg_nr)) 295a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] + 296a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy SIDE_B_OFFSET); 297a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy} 298a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy 299a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthystatic void lcdc_write_chan_mirror(struct sh_mobile_lcdc_chan *chan, 300a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy int reg_nr, unsigned long data) 301a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy{ 302a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] + 303a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy MIRROR_OFFSET); 304cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 305cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 306cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan, 307cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int reg_nr) 308cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 309cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]); 310cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 311cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 312c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic void lcdc_write_overlay(struct sh_mobile_lcdc_overlay *ovl, 313c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int reg, unsigned long data) 314c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 315c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart iowrite32(data, ovl->channel->lcdc->base + reg); 316c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart iowrite32(data, ovl->channel->lcdc->base + reg + SIDE_B_OFFSET); 317c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 318c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 319cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void lcdc_write(struct sh_mobile_lcdc_priv *priv, 320cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long reg_offs, unsigned long data) 321cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 322cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm iowrite32(data, priv->base + reg_offs); 323cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 324cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 325cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv, 326cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long reg_offs) 327cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 328cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return ioread32(priv->base + reg_offs); 329cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 330cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 331cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv, 332cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long reg_offs, 333cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long mask, unsigned long until) 334cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 335cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm while ((lcdc_read(priv, reg_offs) & mask) != until) 336cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm cpu_relax(); 337cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 338cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 339f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 340f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Clock management 341f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 342f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 343f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) 344cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 345f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (atomic_inc_and_test(&priv->hw_usecnt)) { 346f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (priv->dot_clk) 347f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart clk_enable(priv->dot_clk); 348f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart pm_runtime_get_sync(priv->dev); 349f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (priv->meram_dev && priv->meram_dev->pdev) 350f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart pm_runtime_get_sync(&priv->meram_dev->pdev->dev); 351f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 352cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 353cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 354f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) 355f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 356f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (atomic_sub_return(1, &priv->hw_usecnt) == -1) { 357f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (priv->meram_dev && priv->meram_dev->pdev) 358f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart pm_runtime_put_sync(&priv->meram_dev->pdev->dev); 359f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart pm_runtime_put(priv->dev); 360f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (priv->dot_clk) 361f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart clk_disable(priv->dot_clk); 362f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 363f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 364f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 3650a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchartstatic int sh_mobile_lcdc_setup_clocks(struct sh_mobile_lcdc_priv *priv, 3660a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart int clock_source) 367f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 3684774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart struct clk *clk; 369f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart char *str; 370f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 371f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart switch (clock_source) { 372f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case LCDC_CLK_BUS: 373f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart str = "bus_clk"; 374f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart priv->lddckr = LDDCKR_ICKSEL_BUS; 375f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart break; 376f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case LCDC_CLK_PERIPHERAL: 377f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart str = "peripheral_clk"; 378f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart priv->lddckr = LDDCKR_ICKSEL_MIPI; 379f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart break; 380f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case LCDC_CLK_EXTERNAL: 381f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart str = NULL; 382f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart priv->lddckr = LDDCKR_ICKSEL_HDMI; 383f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart break; 384f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart default: 385f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return -EINVAL; 386f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 387f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 3884774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart if (str == NULL) 3894774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart return 0; 3904774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart 3910a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart clk = clk_get(priv->dev, str); 3924774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart if (IS_ERR(clk)) { 3930a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart dev_err(priv->dev, "cannot get dot clock %s\n", str); 3944774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart return PTR_ERR(clk); 395f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 396f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 3974774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart priv->dot_clk = clk; 398f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return 0; 399f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 400f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 401f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 40237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart * Display, panel and deferred I/O 403f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 404f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 405cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void lcdc_sys_write_index(void *handle, unsigned long data) 406cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 407cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch = handle; 408cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 409ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT); 410ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 411ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA | 412ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 413ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 414cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 415cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 416cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void lcdc_sys_write_data(void *handle, unsigned long data) 417cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 418cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch = handle; 419cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 420ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW); 421ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 422ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA | 423ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 424ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 425cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 426cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 427cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic unsigned long lcdc_sys_read_data(void *handle) 428cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 429cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch = handle; 430cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 431ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR); 432ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 433ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA | 434ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 435cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm udelay(1); 436ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 437cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 438ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK; 439cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 440cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 441cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstruct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { 442cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_sys_write_index, 443cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_sys_write_data, 444cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_sys_read_data, 445cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 446cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 4471c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundtstatic int sh_mobile_lcdc_sginit(struct fb_info *info, 4481c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt struct list_head *pagelist) 4491c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt{ 4501c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt struct sh_mobile_lcdc_chan *ch = info->par; 45158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart unsigned int nr_pages_max = ch->fb_size >> PAGE_SHIFT; 4521c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt struct page *page; 4531c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt int nr_pages = 0; 4541c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt 4551c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt sg_init_table(ch->sglist, nr_pages_max); 4561c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt 4571c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt list_for_each_entry(page, pagelist, lru) 4581c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0); 4591c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt 4601c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt return nr_pages; 4611c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt} 4621c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt 4638564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_deferred_io(struct fb_info *info, 4648564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm struct list_head *pagelist) 4658564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 4668564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm struct sh_mobile_lcdc_chan *ch = info->par; 467b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg; 4688564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 4698564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm /* enable clocks before accessing hardware */ 4708564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_clk_on(ch->lcdc); 4718564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 4725c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt /* 4735c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * It's possible to get here without anything on the pagelist via 4745c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * sh_mobile_lcdc_deferred_io_touch() or via a userspace fsync() 4755c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * invocation. In the former case, the acceleration routines are 4765c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * stepped in to when using the framebuffer console causing the 4775c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * workqueue to be scheduled without any dirty pages on the list. 4785c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * 4795c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * Despite this, a panel update is still needed given that the 4805c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * acceleration routines have their own methods for writing in 4815c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * that still need to be updated. 4825c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * 4835c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * The fsync() and empty pagelist case could be optimized for, 4845c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * but we don't bother, as any application exhibiting such 4855c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * behaviour is fundamentally broken anyways. 4865c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt */ 4875c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt if (!list_empty(pagelist)) { 4885c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist); 4895c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt 4905c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt /* trigger panel update */ 491e8363140c02c92c122210e03103aef72dd836664Laurent Pinchart dma_map_sg(ch->lcdc->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 492afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart if (panel->start_transfer) 493afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops); 494ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); 495e8363140c02c92c122210e03103aef72dd836664Laurent Pinchart dma_unmap_sg(ch->lcdc->dev, ch->sglist, nr_pages, 496e8363140c02c92c122210e03103aef72dd836664Laurent Pinchart DMA_TO_DEVICE); 497ef61aae4ddf1dbd0e9b6ad21e2e57632a8fe76f6Magnus Damm } else { 498afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart if (panel->start_transfer) 499afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops); 500ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); 501ef61aae4ddf1dbd0e9b6ad21e2e57632a8fe76f6Magnus Damm } 5028564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 5038564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 5048564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) 5058564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 5068564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm struct fb_deferred_io *fbdefio = info->fbdefio; 5078564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 5088564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm if (fbdefio) 5098564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm schedule_delayed_work(&info->deferred_work, fbdefio->delay); 5108564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 5118564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 51237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchartstatic void sh_mobile_lcdc_display_on(struct sh_mobile_lcdc_chan *ch) 51337c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart{ 514b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg; 51537c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart 5169a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart if (ch->tx_dev) { 517458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart int ret; 518458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart 519458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart ret = ch->tx_dev->ops->display_on(ch->tx_dev); 520458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart if (ret < 0) 5219a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart return; 522458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart 523458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart if (ret == SH_MOBILE_LCDC_DISPLAY_DISCONNECTED) 524458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart ch->info->state = FBINFO_STATE_SUSPENDED; 5259a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart } 5269a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart 52737c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart /* HDMI must be enabled before LCDC configuration */ 528afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart if (panel->display_on) 529afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart panel->display_on(); 53037c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart} 53137c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart 53237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchartstatic void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch) 53337c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart{ 534b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg; 53537c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart 536afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart if (panel->display_off) 537afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart panel->display_off(); 5389a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart 5399a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart if (ch->tx_dev) 5409a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart ch->tx_dev->ops->display_off(ch->tx_dev); 54137c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart} 54237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart 543ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchartstatic bool 544ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchartsh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch, 545e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart const struct fb_videomode *new_mode) 546ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart{ 547ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n", 5482d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.mode.xres, ch->display.mode.yres, 5492d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart new_mode->xres, new_mode->yres); 550ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 551e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart /* It can be a different monitor with an equal video-mode */ 5522d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart if (fb_mode_is_equal(&ch->display.mode, new_mode)) 553ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart return false; 554ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 555ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart dev_dbg(ch->info->dev, "Switching %u -> %u lines\n", 5562d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.mode.yres, new_mode->yres); 5572d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.mode = *new_mode; 558ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 559ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart return true; 560ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart} 561ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 562d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, 563d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart struct fb_info *info); 564ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 565ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchartstatic int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch, 566ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart enum sh_mobile_lcdc_entity_event event, 567e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart const struct fb_videomode *mode, 568e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart const struct fb_monspecs *monspec) 569ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart{ 570ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart struct fb_info *info = ch->info; 571e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart struct fb_var_screeninfo var; 572ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart int ret = 0; 573ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 574ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart switch (event) { 575ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT: 576ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* HDMI plug in */ 577ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart if (lock_fb_info(info)) { 578ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart console_lock(); 579ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 5802d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.width = monspec->max_x * 10; 5812d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.height = monspec->max_y * 10; 582e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart 583e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart if (!sh_mobile_lcdc_must_reconfigure(ch, mode) && 584ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart info->state == FBINFO_STATE_RUNNING) { 585ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* First activation with the default monitor. 586ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart * Just turn on, if we run a resume here, the 587ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart * logo disappears. 588ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart */ 589e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart info->var.width = monspec->max_x * 10; 590e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart info->var.height = monspec->max_y * 10; 591ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart sh_mobile_lcdc_display_on(ch); 592ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } else { 593ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* New monitor or have to wake up */ 594ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart fb_set_suspend(info, 0); 595ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 596ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 597ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart console_unlock(); 598ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart unlock_fb_info(info); 599ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 600ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart break; 601ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 602ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT: 603ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* HDMI disconnect */ 604ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart if (lock_fb_info(info)) { 605ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart console_lock(); 606ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart fb_set_suspend(info, 1); 607ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart console_unlock(); 608ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart unlock_fb_info(info); 609ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 610ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart break; 611ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 612ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE: 613ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* Validate a proposed new mode */ 614e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart fb_videomode_to_var(&var, mode); 615e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart var.bits_per_pixel = info->var.bits_per_pixel; 616e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart var.grayscale = info->var.grayscale; 617d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart ret = sh_mobile_lcdc_check_var(&var, info); 618ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart break; 619ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 620ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 621ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart return ret; 622ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart} 623ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 624f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 625f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Format helpers 626f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 627f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 628105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartstruct sh_mobile_lcdc_format_info { 629105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart u32 fourcc; 630105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart unsigned int bpp; 631105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart bool yuv; 632105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart u32 lddfr; 633105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart}; 634105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 635105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartstatic const struct sh_mobile_lcdc_format_info sh_mobile_format_infos[] = { 636105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart { 637105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_RGB565, 638105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 16, 639105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = false, 640105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_PKF_RGB16, 641105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 642105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_BGR24, 643105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 24, 644105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = false, 645105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_PKF_RGB24, 646105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 647105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_BGR32, 648105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 32, 649105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = false, 650105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_PKF_ARGB32, 651105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 652105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV12, 653105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 12, 654105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 655105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_420, 656105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 657105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV21, 658105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 12, 659105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 660105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_420, 661105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 662105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV16, 663105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 16, 664105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 665105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_422, 666105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 667105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV61, 668105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 16, 669105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 670105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_422, 671105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 672105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV24, 673105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 24, 674105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 675105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_444, 676105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 677105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV42, 678105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 24, 679105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 680105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_444, 681105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, 682105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart}; 683105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 684105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartstatic const struct sh_mobile_lcdc_format_info * 685105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartsh_mobile_format_info(u32 fourcc) 686105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart{ 687105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart unsigned int i; 688105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 689105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart for (i = 0; i < ARRAY_SIZE(sh_mobile_format_infos); ++i) { 690105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart if (sh_mobile_format_infos[i].fourcc == fourcc) 691105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart return &sh_mobile_format_infos[i]; 692105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart } 693105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 694105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart return NULL; 695105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart} 696105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 697f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var) 698f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 699f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (var->grayscale > 1) 700f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return var->grayscale; 701f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 702f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart switch (var->bits_per_pixel) { 703f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case 16: 704f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return V4L2_PIX_FMT_RGB565; 705f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case 24: 706f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return V4L2_PIX_FMT_BGR24; 707f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case 32: 708f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return V4L2_PIX_FMT_BGR32; 709f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart default: 710f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return 0; 711f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 712f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 713f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 714f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var) 715f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 716f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return var->grayscale > 1; 717f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 718f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 719f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 720f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Start, stop and IRQ 721f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 722f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 7238564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) 7248564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 7258564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm struct sh_mobile_lcdc_priv *priv = data; 7262feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm struct sh_mobile_lcdc_chan *ch; 7279dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy unsigned long ldintr; 7282feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm int is_sub; 7292feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm int k; 7308564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 731dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart /* Acknowledge interrupts and disable further VSYNC End IRQs. */ 732dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart ldintr = lcdc_read(priv, _LDINTR); 733dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE); 7348564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 7352feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm /* figure out if this interrupt is for main or sub lcd */ 736ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0; 7372feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7389dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy /* wake up channel and disable clocks */ 7392feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 7402feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm ch = &priv->ch[k]; 7412feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7422feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm if (!ch->enabled) 7432feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm continue; 7442feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 745dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart /* Frame End */ 7469dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy if (ldintr & LDINTR_FS) { 7479dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy if (is_sub == lcdc_chan_is_sublcd(ch)) { 7489dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy ch->frame_end = 1; 7499dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy wake_up(&ch->frame_end_wait); 7502feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7519dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy sh_mobile_lcdc_clk_off(priv); 7529dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy } 7539dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy } 7549dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 7559dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy /* VSYNC End */ 75640331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy if (ldintr & LDINTR_VES) 75740331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy complete(&ch->vsync_completion); 7582feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm } 7592feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7608564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm return IRQ_HANDLED; 7618564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 7628564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 763d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_wait_for_vsync(struct sh_mobile_lcdc_chan *ch) 7644976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart{ 7654976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart unsigned long ldintr; 7664976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart int ret; 7674976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 7684976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart /* Enable VSync End interrupt and be careful not to acknowledge any 7694976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart * pending interrupt. 7704976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart */ 7714976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart ldintr = lcdc_read(ch->lcdc, _LDINTR); 7724976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK; 7734976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart lcdc_write(ch->lcdc, _LDINTR, ldintr); 7744976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 7754976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion, 7764976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart msecs_to_jiffies(100)); 7774976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart if (!ret) 7784976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart return -ETIMEDOUT; 7794976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 7804976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart return 0; 7814976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart} 7824976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 783cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv, 784cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int start) 785cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 786cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long tmp = lcdc_read(priv, _LDCNT2R); 787cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int k; 788cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 789cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* start or stop the lcdc */ 790cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (start) 791ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO); 792cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm else 793ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO); 794cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 795cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* wait until power is applied/stopped on all channels */ 796cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) 797cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled) 798cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm while (1) { 799ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart tmp = lcdc_read_chan(&priv->ch[k], LDPMR) 800ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart & LDPMR_LPS; 801ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart if (start && tmp == LDPMR_LPS) 802cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 803cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!start && tmp == 0) 804cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 805cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm cpu_relax(); 806cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 807cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 808cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!start) 809cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */ 810cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 811cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 8126011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetskistatic void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) 8136011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski{ 8142d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart const struct fb_var_screeninfo *var = &ch->info->var; 8152d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart const struct fb_videomode *mode = &ch->display.mode; 8161c120deb60edd4c19a2109daa98f65f2ad3b9c06Guennadi Liakhovetski unsigned long h_total, hsync_pos, display_h_total; 8176011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski u32 tmp; 8186011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8196011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski tmp = ch->ldmt1r_value; 820ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL; 821ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL; 822b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0; 823b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0; 824b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0; 825b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0; 826b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0; 8276011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDMT1R, tmp); 8286011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8296011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* setup SYS bus */ 830b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart lcdc_write_chan(ch, LDMT2R, ch->cfg->sys_bus_cfg.ldmt2r); 831b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart lcdc_write_chan(ch, LDMT3R, ch->cfg->sys_bus_cfg.ldmt3r); 8326011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8336011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* horizontal configuration */ 8342d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart h_total = mode->xres + mode->hsync_len + mode->left_margin 8352d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart + mode->right_margin; 8366011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski tmp = h_total / 8; /* HTCN */ 83758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */ 8386011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDHCNR, tmp); 8396011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8402d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart hsync_pos = mode->xres + mode->right_margin; 8416011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski tmp = hsync_pos / 8; /* HSYNP */ 8422d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp |= (mode->hsync_len / 8) << 16; /* HSYNW */ 8436011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDHSYNR, tmp); 8446011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8456011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* vertical configuration */ 8462d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp = mode->yres + mode->vsync_len + mode->upper_margin 8472d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart + mode->lower_margin; /* VTLN */ 84858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */ 8496011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDVLNR, tmp); 8506011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8512d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp = mode->yres + mode->lower_margin; /* VSYNP */ 8522d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp |= mode->vsync_len << 16; /* VSYNW */ 8536011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDVSYNR, tmp); 8546011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8556011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* Adjust horizontal synchronisation for HDMI */ 8562d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart display_h_total = mode->xres + mode->hsync_len + mode->left_margin 8572d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart + mode->right_margin; 8582d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16) 8592d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7); 8606011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDHAJR, tmp); 8616011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski} 8626011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 863c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl) 864c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 865c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart u32 format = 0; 866c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 867c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!ovl->enabled) { 868c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); 869c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0); 870c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, 871c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); 872c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return; 873c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 874c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 875c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->base_addr_y = ovl->dma_handle; 876c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->base_addr_c = ovl->base_addr_y + ovl->xres 877c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * ovl->yres_virtual; 878c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 879c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (ovl->mode) { 880c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case LCDC_OVERLAY_BLEND: 881c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT); 882c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 883c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 884c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case LCDC_OVERLAY_ROP3: 885c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = LDBBSIFR_EN | LDBBSIFR_BRSEL 886c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT); 887c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 888c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 889c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 890c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (ovl->format->fourcc) { 891c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_RGB565: 892c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV21: 893c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV61: 894c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV42: 895c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW; 896c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 897c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR24: 898c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV12: 899c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV16: 900c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV24: 901c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB; 902c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 903c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR32: 904c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart default: 905c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_SWPL; 906c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 907c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 908c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 909c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (ovl->format->fourcc) { 910c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_RGB565: 911c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16; 912c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 913c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR24: 914c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24; 915c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 916c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR32: 917c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32; 918c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 919c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV12: 920c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV21: 921c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420; 922c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 923c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV16: 924c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV61: 925c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422; 926c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 927c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV24: 928c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV42: 929c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444; 930c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 931c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 932c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 933c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); 934c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 935c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format); 936c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 937c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index), 938c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->yres << LDBBSSZR_BVSS_SHIFT) | 939c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->xres << LDBBSSZR_BHSS_SHIFT)); 940c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index), 941c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->pos_y << LDBBLOCR_CVLC_SHIFT) | 942c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->pos_x << LDBBLOCR_CHLC_SHIFT)); 943c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index), 944c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pitch << LDBBSMWR_BSMW_SHIFT); 945c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 946c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); 947c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); 948c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 949c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, 950c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); 951c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 952c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 9539a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart/* 954d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart * __sh_mobile_lcdc_start - Configure and start the LCDC 9559a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * @priv: LCDC device 9569a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * 9579a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * Configure all enabled channels and start the LCDC device. All external 9589a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * devices (clocks, MERAM, panels, ...) are not touched by this function. 9599a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 9609a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchartstatic void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 961cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 962cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch; 963cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long tmp; 9649a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int k, m; 9658564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 9669a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Enable LCDC channels. Read data from external memory, avoid using the 9679a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * BEU for now. 9689a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 9699a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled); 970cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 9719a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Stop the LCDC first and disable all interrupts. */ 972cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm sh_mobile_lcdc_start_stop(priv, 0); 9739a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDINTR, 0); 974cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 9759a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Configure power supply, dot clocks and start them. */ 976cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm tmp = priv->lddckr; 977cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 978cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 9799a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (!ch->enabled) 980cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm continue; 981cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 9829a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Power supply */ 9839a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDPMR, 0); 9849a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 985b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart m = ch->cfg->clock_divider; 986cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!m) 987cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm continue; 988cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 989505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider 990505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart * denominator. 991505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart */ 992505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart lcdc_write_chan(ch, LDDCKPAT1R, 0); 993505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); 994505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart 995cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (m == 1) 996ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart m = LDDCKR_MOSEL; 997cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); 998cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 999cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1000cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_write(priv, _LDDCKR, tmp); 1001cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_write(priv, _LDDCKSTPR, 0); 1002cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0); 1003cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10049a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Setup geometry, format, frame buffer memory and operation mode. */ 1005cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1006cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 1007cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!ch->enabled) 1008cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm continue; 1009cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10106011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski sh_mobile_lcdc_geometry(ch); 1011cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1012fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart tmp = ch->format->lddfr; 1013edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart 1014fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart if (ch->format->yuv) { 101558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart switch (ch->colorspace) { 1016edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_COLORSPACE_REC709: 1017edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp |= LDDFR_CF1; 101853b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia break; 1019edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_COLORSPACE_JPEG: 1020edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp |= LDDFR_CF0; 102153b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia break; 102253b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia } 1023417d48274e755e537bae60461558c1f63a4e14deMagnus Damm } 10247caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10259a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDDFR, tmp); 102672c04af9a2d57b7945cf3de8e71461bd80695d50Laurent Pinchart lcdc_write_chan(ch, LDMLSR, ch->line_size); 10279a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); 1028fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart if (ch->format->yuv) 10299a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); 10307caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10319a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* When using deferred I/O mode, configure the LCDC for one-shot 10329a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * operation and enable the frame end interrupt. Otherwise use 10339a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * continuous read mode. 10349a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 10359a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (ch->ldmt1r_value & LDMT1R_IFM && 1036b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart ch->cfg->sys_bus_cfg.deferred_io_msec) { 10379a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSM1R, LDSM1R_OS); 10389a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDINTR, LDINTR_FE); 10399a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } else { 10409a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSM1R, 0); 10419a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10429a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10437caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10449a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Word and long word swap. */ 1045fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart switch (priv->ch[0].format->fourcc) { 1046edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_RGB565: 1047edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV21: 1048edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV61: 1049edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV42: 1050edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp = LDDDSR_LS | LDDDSR_WS; 1051edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1052edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR24: 1053edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV12: 1054edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV16: 1055edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV24: 10569a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS; 1057edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1058edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR32: 1059edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart default: 1060edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp = LDDDSR_LS; 1061edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 10629a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10639a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDDDSR, tmp); 10647caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10659a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Enable the display output. */ 10669a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDCNT1R, LDCNT1R_DE); 10679a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart sh_mobile_lcdc_start_stop(priv, 1); 10689a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart priv->started = 1; 10699a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart} 1070cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10719a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchartstatic int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 10729a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart{ 10739a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart struct sh_mobile_meram_info *mdev = priv->meram_dev; 10749a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart struct sh_mobile_lcdc_chan *ch; 10759a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart unsigned long tmp; 10769a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int ret; 10779a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int k; 1078cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10799a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* enable clocks before accessing the hardware */ 10809a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 10819a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (priv->ch[k].enabled) 10829a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart sh_mobile_lcdc_clk_on(priv); 10839a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10848564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 10859a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* reset */ 10869a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR); 10879a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0); 10888564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 10899a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1090b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_panel_cfg *panel; 10918564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 109237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart ch = &priv->ch[k]; 10939a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (!ch->enabled) 10949a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart continue; 10959a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 1096b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart panel = &ch->cfg->panel_cfg; 1097afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart if (panel->setup_sys) { 1098afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart ret = panel->setup_sys(ch, &sh_mobile_lcdc_sys_bus_ops); 10999a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (ret) 11009a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart return ret; 11018564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm } 1102cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 1103cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 11049a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Compute frame buffer base address and pitch for each channel. */ 11059a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 11069a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int pixelformat; 11074a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart void *cache; 1108cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 11099a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch = &priv->ch[k]; 11109a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (!ch->enabled) 11119a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart continue; 1112cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 111358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->base_addr_y = ch->dma_handle; 111458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual; 111572c04af9a2d57b7945cf3de8e71461bd80695d50Laurent Pinchart ch->line_size = ch->pitch; 11169a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11179a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Enable MERAM if possible. */ 11186e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart if (mdev == NULL || ch->cfg->meram_cfg == NULL) 11199a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart continue; 11209a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11214a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart /* Free the allocated MERAM cache. */ 11224a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart if (ch->cache) { 11236e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_free(mdev, ch->cache); 11244a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart ch->cache = NULL; 11259a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 11269a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 1127fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart switch (ch->format->fourcc) { 1128edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV12: 1129edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV21: 1130edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV16: 1131edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV61: 11329a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart pixelformat = SH_MOBILE_MERAM_PF_NV; 1133edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1134edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV24: 1135edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV42: 1136edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart pixelformat = SH_MOBILE_MERAM_PF_NV24; 1137edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1138edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_RGB565: 1139edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR24: 1140edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR32: 1141edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart default: 1142edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart pixelformat = SH_MOBILE_MERAM_PF_RGB; 1143edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1144edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart } 11459a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11466e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg, 1147b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart ch->pitch, ch->yres, pixelformat, 114872c04af9a2d57b7945cf3de8e71461bd80695d50Laurent Pinchart &ch->line_size); 11494a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart if (!IS_ERR(cache)) { 11506e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_update(mdev, cache, 115197d16fe69b6499a14a0c85c053f7bef54ce992a4Laurent Pinchart ch->base_addr_y, ch->base_addr_c, 115297d16fe69b6499a14a0c85c053f7bef54ce992a4Laurent Pinchart &ch->base_addr_y, &ch->base_addr_c); 11534a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart ch->cache = cache; 115497d16fe69b6499a14a0c85c053f7bef54ce992a4Laurent Pinchart } 11559a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 11569a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 1157c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) { 1158c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k]; 1159c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1160c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1161c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 11629a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Start the LCDC. */ 11639a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart __sh_mobile_lcdc_start(priv); 11649a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11659a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Setup deferred I/O, tell the board code to enable the panels, and 11669a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * turn backlight on. 11679a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 1168cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1169cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 117021bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm if (!ch->enabled) 117121bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm continue; 117221bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm 1173b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp = ch->cfg->sys_bus_cfg.deferred_io_msec; 11749a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (ch->ldmt1r_value & LDMT1R_IFM && tmp) { 11759a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; 11769a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch->defio.delay = msecs_to_jiffies(tmp); 11779a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch->info->fbdefio = &ch->defio; 11789a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart fb_deferred_io_init(ch->info); 11799a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 11809a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 118137c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_on(ch); 11823b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 11833b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot if (ch->bl) { 11843b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot ch->bl->props.power = FB_BLANK_UNBLANK; 11853b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_update_status(ch->bl); 11863b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot } 1187cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 1188cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1189cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return 0; 1190cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 1191cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1192cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) 1193cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 1194cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch; 1195cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int k; 1196cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 11972feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm /* clean up deferred io and ask board code to disable panel */ 1198cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1199cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 120021bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm if (!ch->enabled) 120121bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm continue; 12028564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 12032feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm /* deferred io mode: 12042feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm * flush frame, and wait for frame end interrupt 12052feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm * clean up deferred io and enable clock 12062feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm */ 12075ef6b505d9df45558402bdb823a078840a6a26c4Guennadi Liakhovetski if (ch->info && ch->info->fbdefio) { 12082feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm ch->frame_end = 0; 1209e33afddca174171a68d57476ead8947476ab9240Paul Mundt schedule_delayed_work(&ch->info->deferred_work, 0); 12102feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm wait_event(ch->frame_end_wait, ch->frame_end); 1211e33afddca174171a68d57476ead8947476ab9240Paul Mundt fb_deferred_io_cleanup(ch->info); 1212e33afddca174171a68d57476ead8947476ab9240Paul Mundt ch->info->fbdefio = NULL; 12132feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm sh_mobile_lcdc_clk_on(priv); 12148564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm } 12152feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 12163b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot if (ch->bl) { 12173b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot ch->bl->props.power = FB_BLANK_POWERDOWN; 12183b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_update_status(ch->bl); 12193b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot } 12203b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 122137c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_off(ch); 12227caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 12234a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart /* Free the MERAM cache. */ 12244a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart if (ch->cache) { 12256e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_free(priv->meram_dev, ch->cache); 12264a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart ch->cache = 0; 12277caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia } 12287caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 1229cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 1230cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1231cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* stop the lcdc */ 12328e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm if (priv->started) { 12338e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm sh_mobile_lcdc_start_stop(priv, 0); 12348e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm priv->started = 0; 12358e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm } 1236b51339fff240ff179730f8963a758147fd60f3ecMagnus Damm 12378564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm /* stop clocks */ 12388564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) 12398564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm if (priv->ch[k].enabled) 12408564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_clk_off(priv); 1241cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 1242cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1243c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, 1244c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info) 1245c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1246c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->xres > MAX_XRES || var->yres > MAX_YRES) 1247c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1248c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1249c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Make sure the virtual resolution is at least as big as the visible 1250c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * resolution. 1251c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1252c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->xres_virtual < var->xres) 1253c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->xres_virtual = var->xres; 1254c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->yres_virtual < var->yres) 1255c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->yres_virtual = var->yres; 1256c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1257c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (sh_mobile_format_is_fourcc(var)) { 1258c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const struct sh_mobile_lcdc_format_info *format; 1259c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1260c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = sh_mobile_format_info(var->grayscale); 1261c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (format == NULL) 1262c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1263c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = format->bpp; 1264c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1265c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Default to RGB and JPEG color-spaces for RGB and YUV formats 1266c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * respectively. 1267c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1268c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!format->yuv) 1269c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->colorspace = V4L2_COLORSPACE_SRGB; 1270c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else if (var->colorspace != V4L2_COLORSPACE_REC709) 1271c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->colorspace = V4L2_COLORSPACE_JPEG; 1272c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else { 1273c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->bits_per_pixel <= 16) { /* RGB 565 */ 1274c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = 16; 1275c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.offset = 11; 1276c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.length = 5; 1277c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.offset = 5; 1278c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.length = 6; 1279c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.offset = 0; 1280c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.length = 5; 1281c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.offset = 0; 1282c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.length = 0; 1283c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ 1284c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = 24; 1285c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.offset = 16; 1286c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.length = 8; 1287c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.offset = 8; 1288c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.length = 8; 1289c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.offset = 0; 1290c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.length = 8; 1291c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.offset = 0; 1292c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.length = 0; 1293c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ 1294c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = 32; 1295c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.offset = 16; 1296c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.length = 8; 1297c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.offset = 8; 1298c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.length = 8; 1299c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.offset = 0; 1300c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.length = 8; 1301c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.offset = 24; 1302c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.length = 8; 1303c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else 1304c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1305c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1306c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.msb_right = 0; 1307c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.msb_right = 0; 1308c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.msb_right = 0; 1309c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.msb_right = 0; 1310c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1311c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1312c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Make sure we don't exceed our allocated memory. */ 1313c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > 1314c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.smem_len) 1315c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1316c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1317c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1318c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1319c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1320c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart/* ----------------------------------------------------------------------------- 1321c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * Frame buffer operations - Overlays 1322c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1323c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1324c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1325c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf) 1326c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1327c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1328c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1329c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1330c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->alpha); 1331c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1332c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1333c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1334c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_alpha_store(struct device *dev, struct device_attribute *attr, 1335c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1336c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1337c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1338c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1339c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int alpha; 1340c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1341c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1342c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart alpha = simple_strtoul(buf, &endp, 10); 1343c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1344c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1345c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1346c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1347c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1348c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1349c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (alpha > 255) 1350c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1351c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1352c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->alpha != alpha) { 1353c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->alpha = alpha; 1354c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1355c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled) 1356c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1357c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1358c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1359c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1360c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1361c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1362c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1363c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_mode_show(struct device *dev, struct device_attribute *attr, char *buf) 1364c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1365c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1366c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1367c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1368c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->mode); 1369c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1370c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1371c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1372c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_mode_store(struct device *dev, struct device_attribute *attr, 1373c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1374c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1375c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1376c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1377c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int mode; 1378c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1379c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1380c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart mode = simple_strtoul(buf, &endp, 10); 1381c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1382c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1383c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1384c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1385c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1386c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1387c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (mode != LCDC_OVERLAY_BLEND && mode != LCDC_OVERLAY_ROP3) 1388c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1389c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1390c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->mode != mode) { 1391c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->mode = mode; 1392c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1393c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->enabled) 1394c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1395c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1396c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1397c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1398c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1399c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1400c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1401c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_position_show(struct device *dev, struct device_attribute *attr, 1402c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *buf) 1403c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1404c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1405c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1406c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1407c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%d,%d\n", ovl->pos_x, ovl->pos_y); 1408c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1409c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1410c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1411c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_position_store(struct device *dev, struct device_attribute *attr, 1412c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1413c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1414c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1415c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1416c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1417c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int pos_x; 1418c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int pos_y; 1419c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1420c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart pos_x = simple_strtol(buf, &endp, 10); 1421c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (*endp != ',') 1422c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1423c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1424c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart pos_y = simple_strtol(endp + 1, &endp, 10); 1425c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1426c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1427c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1428c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1429c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1430c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1431c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) { 1432c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_x = pos_x; 1433c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_y = pos_y; 1434c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1435c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->enabled) 1436c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1437c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1438c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1439c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1440c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1441c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1442c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1443c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_rop3_show(struct device *dev, struct device_attribute *attr, char *buf) 1444c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1445c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1446c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1447c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1448c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->rop3); 1449c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1450c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1451c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1452c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_rop3_store(struct device *dev, struct device_attribute *attr, 1453c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1454c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1455c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1456c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1457c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int rop3; 1458c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1459c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1460c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart rop3 = !!simple_strtoul(buf, &endp, 10); 1461c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1462c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1463c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1464c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1465c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1466c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1467c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (rop3 > 255) 1468c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1469c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1470c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->rop3 != rop3) { 1471c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->rop3 = rop3; 1472c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1473c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled) 1474c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1475c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1476c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1477c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1478c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1479c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1480c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic const struct device_attribute overlay_sysfs_attrs[] = { 1481c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_alpha, S_IRUGO|S_IWUSR, 1482c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_alpha_show, overlay_alpha_store), 1483c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_mode, S_IRUGO|S_IWUSR, 1484c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_mode_show, overlay_mode_store), 1485c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_position, S_IRUGO|S_IWUSR, 1486c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_position_show, overlay_position_store), 1487c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_rop3, S_IRUGO|S_IWUSR, 1488c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_rop3_show, overlay_rop3_store), 1489c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 1490c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1491c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = { 1492c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .id = "SH Mobile LCDC", 1493c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .type = FB_TYPE_PACKED_PIXELS, 1494c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .visual = FB_VISUAL_TRUECOLOR, 1495c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .accel = FB_ACCEL_NONE, 1496c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .xpanstep = 0, 1497c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .ypanstep = 1, 1498c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .ywrapstep = 0, 1499c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .capabilities = FB_CAP_FOURCC, 1500c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 1501c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1502c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var, 1503c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info) 1504c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1505c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1506c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base_addr_y; 1507c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base_addr_c; 1508c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long pan_offset; 1509c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long c_offset; 1510c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1511c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!ovl->format->yuv) 1512c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart pan_offset = var->yoffset * ovl->pitch 1513c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart + var->xoffset * (ovl->format->bpp / 8); 1514c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 1515c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart pan_offset = var->yoffset * ovl->pitch + var->xoffset; 1516c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1517c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (pan_offset == ovl->pan_offset) 1518c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; /* No change, do nothing */ 1519c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1520c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Set the source address for the next refresh */ 1521c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart base_addr_y = ovl->dma_handle + pan_offset; 1522c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1523c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->base_addr_y = base_addr_y; 1524c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->base_addr_c = base_addr_y; 1525c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1526c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->format->yuv) { 1527c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Set Y offset */ 1528c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart c_offset = var->yoffset * ovl->pitch 1529c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * (ovl->format->bpp - 8) / 8; 1530c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart base_addr_c = ovl->dma_handle 1531c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart + ovl->xres * ovl->yres_virtual 1532c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart + c_offset; 1533c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Set X offset */ 1534c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->format->fourcc == V4L2_PIX_FMT_NV24) 1535c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart base_addr_c += 2 * var->xoffset; 1536c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 1537c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart base_addr_c += var->xoffset; 1538c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1539c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->base_addr_c = base_addr_c; 1540c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1541c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1542c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); 1543c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); 1544c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1545c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pan_offset = pan_offset; 1546c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1547c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1548c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1549c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1550c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_ioctl(struct fb_info *info, unsigned int cmd, 1551c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long arg) 1552c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1553c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1554c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1555c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (cmd) { 1556c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case FBIO_WAITFORVSYNC: 1557c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return sh_mobile_lcdc_wait_for_vsync(ovl->channel); 1558c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1559c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart default: 1560c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -ENOIOCTLCMD; 1561c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1562c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1563c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1564c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_check_var(struct fb_var_screeninfo *var, 1565c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info) 1566c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1567c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return __sh_mobile_lcdc_check_var(var, info); 1568c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1569c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1570c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_set_par(struct fb_info *info) 1571c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1572c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1573c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1574c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->format = 1575c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_format_info(sh_mobile_format_fourcc(&info->var)); 1576c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1577c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres = info->var.xres; 1578c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres_virtual = info->var.xres_virtual; 1579c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres = info->var.yres; 1580c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres_virtual = info->var.yres_virtual; 1581c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1582c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->format->yuv) 1583c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pitch = info->var.xres; 1584c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 1585c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pitch = info->var.xres * ovl->format->bpp / 8; 1586c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1587c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1588c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1589c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.line_length = ovl->pitch; 1590c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1591c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (sh_mobile_format_is_fourcc(&info->var)) { 1592c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.type = FB_TYPE_FOURCC; 1593c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 1594c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else { 1595c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.type = FB_TYPE_PACKED_PIXELS; 1596c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 1597c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1598c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1599c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1600c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1601c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1602c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart/* Overlay blanking. Disable the overlay when blanked. */ 1603c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info) 1604c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1605c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1606c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1607c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->enabled = !blank; 1608c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1609c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1610c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Prevent the backlight from receiving a blanking event by returning 1611c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * a non-zero value. 1612c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1613c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 1; 1614c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1615c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1616c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic struct fb_ops sh_mobile_lcdc_overlay_ops = { 1617c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .owner = THIS_MODULE, 1618c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_read = fb_sys_read, 1619c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_write = fb_sys_write, 1620c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_fillrect = sys_fillrect, 1621c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_copyarea = sys_copyarea, 1622c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_imageblit = sys_imageblit, 1623c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_blank = sh_mobile_lcdc_overlay_blank, 1624c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_pan_display = sh_mobile_lcdc_overlay_pan, 1625c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_ioctl = sh_mobile_lcdc_overlay_ioctl, 1626c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_check_var = sh_mobile_lcdc_overlay_check_var, 1627c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_set_par = sh_mobile_lcdc_overlay_set_par, 1628c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 1629c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1630c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic void 1631c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl) 1632c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1633c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = ovl->info; 1634c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1635c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL || info->dev == NULL) 1636c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return; 1637c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1638c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unregister_framebuffer(ovl->info); 1639c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1640c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1641c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int __devinit 1642c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl) 1643c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1644c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc; 1645c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = ovl->info; 1646c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int i; 1647c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int ret; 1648c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1649c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL) 1650c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1651c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1652c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = register_framebuffer(info); 1653c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 1654c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 1655c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1656c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n", 1657c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dev_name(lcdc->dev), ovl->index, info->var.xres, 1658c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->var.yres, info->var.bits_per_pixel); 1659c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1660c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) { 1661c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]); 1662c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 1663c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 1664c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1665c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1666c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1667c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1668c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1669c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic void 1670c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl) 1671c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1672c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = ovl->info; 1673c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1674c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL || info->device == NULL) 1675c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return; 1676c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1677c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart framebuffer_release(info); 1678c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1679c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1680c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int __devinit 1681c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) 1682c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1683c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc; 1684c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_var_screeninfo *var; 1685c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info; 1686c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1687c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Allocate and initialize the frame buffer device. */ 1688c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info = framebuffer_alloc(0, priv->dev); 1689c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL) { 1690c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dev_err(priv->dev, "unable to allocate fb_info\n"); 1691c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -ENOMEM; 1692c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1693c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1694c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->info = info; 1695c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1696c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->flags = FBINFO_FLAG_DEFAULT; 1697c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fbops = &sh_mobile_lcdc_overlay_ops; 1698c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->device = priv->dev; 1699c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->screen_base = ovl->fb_mem; 1700c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->par = ovl; 1701c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1702c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Initialize fixed screen information. Restrict pan to 2 lines steps 1703c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * for NV12 and NV21. 1704c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1705c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix = sh_mobile_lcdc_overlay_fix; 1706c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart snprintf(info->fix.id, sizeof(info->fix.id), 1707c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart "SH Mobile LCDC Overlay %u", ovl->index); 1708c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.smem_start = ovl->dma_handle; 1709c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.smem_len = ovl->fb_size; 1710c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.line_length = ovl->pitch; 1711c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1712c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->format->yuv) 1713c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 1714c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 1715c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 1716c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1717c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->format->fourcc == V4L2_PIX_FMT_NV12 || 1718c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->format->fourcc == V4L2_PIX_FMT_NV21) 1719c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.ypanstep = 2; 1720c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1721c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Initialize variable screen information. */ 1722c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var = &info->var; 1723c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart memset(var, 0, sizeof(*var)); 1724c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->xres = ovl->xres; 1725c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->yres = ovl->yres; 1726c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->xres_virtual = ovl->xres_virtual; 1727c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->yres_virtual = ovl->yres_virtual; 1728c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->activate = FB_ACTIVATE_NOW; 1729c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1730c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Use the legacy API by default for RGB formats, and the FOURCC API 1731c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * for YUV formats. 1732c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1733c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!ovl->format->yuv) 1734c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = ovl->format->bpp; 1735c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 1736c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->grayscale = ovl->format->fourcc; 1737c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1738c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return sh_mobile_lcdc_overlay_check_var(var, info); 1739c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1740c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1741f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 1742c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * Frame buffer operations - main frame buffer 1743f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 1744cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1745cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic int sh_mobile_lcdc_setcolreg(u_int regno, 1746cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm u_int red, u_int green, u_int blue, 1747cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm u_int transp, struct fb_info *info) 1748cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 1749cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm u32 *palette = info->pseudo_palette; 1750cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1751cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (regno >= PALETTE_NR) 1752cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return -EINVAL; 1753cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1754cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* only FB_VISUAL_TRUECOLOR supported */ 1755cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1756cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm red >>= 16 - info->var.red.length; 1757cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm green >>= 16 - info->var.green.length; 1758cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm blue >>= 16 - info->var.blue.length; 1759cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm transp >>= 16 - info->var.transp.length; 1760cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1761cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm palette[regno] = (red << info->var.red.offset) | 1762cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm (green << info->var.green.offset) | 1763cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm (blue << info->var.blue.offset) | 1764cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm (transp << info->var.transp.offset); 1765cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1766cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return 0; 1767cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 1768cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 17693281e54c80195b90ed12a5b6cddef4ab42e656e1Laurent Pinchartstatic const struct fb_fix_screeninfo sh_mobile_lcdc_fix = { 1770cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .id = "SH Mobile LCDC", 1771cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .type = FB_TYPE_PACKED_PIXELS, 1772cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .visual = FB_VISUAL_TRUECOLOR, 1773cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .accel = FB_ACCEL_NONE, 17749dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy .xpanstep = 0, 17759dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy .ypanstep = 1, 17769dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy .ywrapstep = 0, 1777edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart .capabilities = FB_CAP_FOURCC, 1778cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 1779cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 17808564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_fillrect(struct fb_info *info, 17818564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm const struct fb_fillrect *rect) 17828564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 17838564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sys_fillrect(info, rect); 17848564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_deferred_io_touch(info); 17858564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 17868564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 17878564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_copyarea(struct fb_info *info, 17888564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm const struct fb_copyarea *area) 17898564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 17908564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sys_copyarea(info, area); 17918564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_deferred_io_touch(info); 17928564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 17938564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 17948564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_imageblit(struct fb_info *info, 17958564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm const struct fb_image *image) 17968564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 17978564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sys_imageblit(info, image); 17988564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_deferred_io_touch(info); 17998564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 18008564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 1801d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var, 1802d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart struct fb_info *info) 18039dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy{ 18049dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy struct sh_mobile_lcdc_chan *ch = info->par; 180592e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy struct sh_mobile_lcdc_priv *priv = ch->lcdc; 180692e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy unsigned long ldrcntr; 180792e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy unsigned long new_pan_offset; 18086e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart unsigned long base_addr_y, base_addr_c = 0; 180953b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia unsigned long c_offset; 181092e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy 181158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (!ch->format->yuv) 181258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart new_pan_offset = var->yoffset * ch->pitch 181358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart + var->xoffset * (ch->format->bpp / 8); 181453b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia else 181558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart new_pan_offset = var->yoffset * ch->pitch + var->xoffset; 18169dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 181792e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy if (new_pan_offset == ch->pan_offset) 18189dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy return 0; /* No change, do nothing */ 18199dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 182092e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy ldrcntr = lcdc_read(priv, _LDRCNTR); 18219dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 182292e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy /* Set the source address for the next refresh */ 182353b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia base_addr_y = ch->dma_handle + new_pan_offset; 182458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ch->format->yuv) { 182553b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia /* Set y offset */ 182658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart c_offset = var->yoffset * ch->pitch 182758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart * (ch->format->bpp - 8) / 8; 182858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart base_addr_c = ch->dma_handle + ch->xres * ch->yres_virtual 1829dc1d5adab5cc57eb732407d80c9e7ae48891ffcaLaurent Pinchart + c_offset; 183053b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia /* Set x offset */ 1831fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart if (ch->format->fourcc == V4L2_PIX_FMT_NV24) 183253b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia base_addr_c += 2 * var->xoffset; 183353b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia else 183453b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia base_addr_c += var->xoffset; 183549d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart } 183653b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia 18376e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart if (ch->cache) 18386e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_update(priv->meram_dev, ch->cache, 18396e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart base_addr_y, base_addr_c, 18406e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart &base_addr_y, &base_addr_c); 18417caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 184249d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart ch->base_addr_y = base_addr_y; 184349d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart ch->base_addr_c = base_addr_c; 18447caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 184549d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); 184658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ch->format->yuv) 184749d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); 184853b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia 184992e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy if (lcdc_chan_is_sublcd(ch)) 185092e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); 185192e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy else 185292e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS); 185392e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy 185492e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy ch->pan_offset = new_pan_offset; 185592e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy 185692e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy sh_mobile_lcdc_deferred_io_touch(info); 18579dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 18589dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy return 0; 18599dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy} 18609dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 1861d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_ioctl(struct fb_info *info, unsigned int cmd, 1862d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart unsigned long arg) 186340331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy{ 1864d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart struct sh_mobile_lcdc_chan *ch = info->par; 186540331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy int retval; 186640331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 186740331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy switch (cmd) { 186840331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy case FBIO_WAITFORVSYNC: 1869d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart retval = sh_mobile_lcdc_wait_for_vsync(ch); 187040331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy break; 187140331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 187240331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy default: 187340331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy retval = -ENOIOCTLCMD; 187440331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy break; 187540331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy } 187640331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy return retval; 187740331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy} 187840331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 1879dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetskistatic void sh_mobile_fb_reconfig(struct fb_info *info) 1880dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1881dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 18822d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart struct fb_var_screeninfo var; 18832d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart struct fb_videomode mode; 1884dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct fb_event event; 1885dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski int evnt = FB_EVENT_MODE_CHANGE_ALL; 1886dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1887dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par)) 1888dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* More framebuffer users are active */ 1889dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return; 1890dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 18912d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart fb_var_to_videomode(&mode, &info->var); 1892dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 18932d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart if (fb_mode_is_equal(&ch->display.mode, &mode)) 1894dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return; 1895dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1896dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* Display has been re-plugged, framebuffer is free now, reconfigure */ 18972d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var = info->var; 18982d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart fb_videomode_to_var(&var, &ch->display.mode); 18992d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var.width = ch->display.width; 19002d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var.height = ch->display.height; 19012d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var.activate = FB_ACTIVATE_NOW; 19022d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart 19032d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart if (fb_set_var(info, &var) < 0) 1904dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* Couldn't reconfigure, hopefully, can continue as before */ 1905dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return; 1906dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1907dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* 1908dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * fb_set_var() calls the notifier change internally, only if 1909dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a 1910dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * user event, we have to call the chain ourselves. 1911dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski */ 1912dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski event.info = info; 19132d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart event.data = &ch->display.mode; 1914dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski fb_notifier_call_chain(evnt, &event); 1915dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 1916dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1917dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski/* 1918dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * Locking: both .fb_release() and .fb_open() are called with info->lock held if 1919dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * user == 1, or with console sem held, if user == 0. 1920dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski */ 1921d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_release(struct fb_info *info, int user) 1922dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1923dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 1924dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1925dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_lock(&ch->open_lock); 1926dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count); 1927dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1928dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski ch->use_count--; 1929dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1930dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* Nothing to reconfigure, when called from fbcon */ 1931dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski if (user) { 1932ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 1933dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski sh_mobile_fb_reconfig(info); 1934ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 1935dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski } 1936dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1937dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_unlock(&ch->open_lock); 1938dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1939dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return 0; 1940dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 1941dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1942d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_open(struct fb_info *info, int user) 1943dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1944dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 1945dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1946dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_lock(&ch->open_lock); 1947dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski ch->use_count++; 1948dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1949dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count); 1950dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_unlock(&ch->open_lock); 1951dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1952dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return 0; 1953dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 1954dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1955d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, 1956d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart struct fb_info *info) 1957dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1958dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 1959417d48274e755e537bae60461558c1f63a4e14deMagnus Damm struct sh_mobile_lcdc_priv *p = ch->lcdc; 19600386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int best_dist = (unsigned int)-1; 19610386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int best_xres = 0; 19620386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int best_yres = 0; 19630386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int i; 1964c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int ret; 19650386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19660386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart /* If board code provides us with a list of available modes, make sure 19670386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * we use one of them. Find the mode closest to the requested one. The 19680386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * distance between two modes is defined as the size of the 19690386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * non-overlapping parts of the two rectangles. 19700386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart */ 1971b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart for (i = 0; i < ch->cfg->num_modes; ++i) { 1972b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct fb_videomode *mode = &ch->cfg->lcd_modes[i]; 19730386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int dist; 19740386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19750386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart /* We can only round up. */ 19760386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart if (var->xres > mode->xres || var->yres > mode->yres) 19770386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart continue; 19780386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19790386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart dist = var->xres * var->yres + mode->xres * mode->yres 19800386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart - 2 * min(var->xres, mode->xres) 19810386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * min(var->yres, mode->yres); 19820386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19830386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart if (dist < best_dist) { 19840386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart best_xres = mode->xres; 19850386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart best_yres = mode->yres; 19860386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart best_dist = dist; 19870386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart } 1988dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski } 1989417d48274e755e537bae60461558c1f63a4e14deMagnus Damm 19900386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart /* If no available mode can be used, return an error. */ 1991b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart if (ch->cfg->num_modes != 0) { 19920386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart if (best_dist == (unsigned int)-1) 19930386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart return -EINVAL; 19940386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19950386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart var->xres = best_xres; 19960386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart var->yres = best_yres; 19970386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart } 19980386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 1999c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = __sh_mobile_lcdc_check_var(var, info); 2000c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 2001c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 20020386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 2003edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart /* only accept the forced_fourcc for dual channel configurations */ 2004edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart if (p->forced_fourcc && 2005edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart p->forced_fourcc != sh_mobile_format_fourcc(var)) 2006417d48274e755e537bae60461558c1f63a4e14deMagnus Damm return -EINVAL; 2007417d48274e755e537bae60461558c1f63a4e14deMagnus Damm 2008dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return 0; 2009dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 201040331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 2011d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_set_par(struct fb_info *info) 2012ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart{ 2013ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart struct sh_mobile_lcdc_chan *ch = info->par; 2014ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart int ret; 2015ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart 2016ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart sh_mobile_lcdc_stop(ch->lcdc); 201791fba48d59666718e3d3e86964755b80d39cdbddLaurent Pinchart 2018fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var)); 201958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->colorspace = info->var.colorspace; 202058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 202158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres = info->var.xres; 202258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres_virtual = info->var.xres_virtual; 202358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres = info->var.yres; 202458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres_virtual = info->var.yres_virtual; 202558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 202658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ch->format->yuv) 202758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->pitch = info->var.xres; 202858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart else 202958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->pitch = info->var.xres * ch->format->bpp / 8; 2030fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart 2031ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart ret = sh_mobile_lcdc_start(ch->lcdc); 203258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ret < 0) 2033ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart dev_err(info->dev, "%s: unable to restart LCDC\n", __func__); 203458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 203558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.line_length = ch->pitch; 2036ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart 2037edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart if (sh_mobile_format_is_fourcc(&info->var)) { 2038edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.type = FB_TYPE_FOURCC; 2039edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 2040edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart } else { 2041edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.type = FB_TYPE_PACKED_PIXELS; 2042edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 2043edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart } 2044edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart 2045ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart return ret; 2046ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart} 2047ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart 20488857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot/* 20498857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * Screen blanking. Behavior is as follows: 20508857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_UNBLANK: screen unblanked, clocks enabled 20518857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_NORMAL: screen blanked, clocks enabled 20528857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_VSYNC, 20538857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_HSYNC, 20548857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_POWEROFF: screen blanked, clocks disabled 20558857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot */ 20568857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbotstatic int sh_mobile_lcdc_blank(int blank, struct fb_info *info) 20578857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot{ 20588857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot struct sh_mobile_lcdc_chan *ch = info->par; 20598857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot struct sh_mobile_lcdc_priv *p = ch->lcdc; 20608857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot 20618857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* blank the screen? */ 20628857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) { 20638857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot struct fb_fillrect rect = { 206458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart .width = ch->xres, 206558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart .height = ch->yres, 20668857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot }; 20678857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot sh_mobile_lcdc_fillrect(info, &rect); 20688857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 20698857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* turn clocks on? */ 20708857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) { 20718857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot sh_mobile_lcdc_clk_on(p); 20728857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 20738857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* turn clocks off? */ 20748857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) { 20758857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* make sure the screen is updated with the black fill before 20768857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * switching the clocks off. one vsync is not enough since 20778857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * blanking may occur in the middle of a refresh. deferred io 20788857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * mode will reenable the clocks and update the screen in time, 20798857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * so it does not need this. */ 20808857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (!info->fbdefio) { 2081d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart sh_mobile_lcdc_wait_for_vsync(ch); 2082d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart sh_mobile_lcdc_wait_for_vsync(ch); 20838857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 20848857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot sh_mobile_lcdc_clk_off(p); 20858857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 20868857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot 20878857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot ch->blank_status = blank; 20888857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot return 0; 20898857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot} 20908857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot 2091cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic struct fb_ops sh_mobile_lcdc_ops = { 20929dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy .owner = THIS_MODULE, 2093cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .fb_setcolreg = sh_mobile_lcdc_setcolreg, 20942540c111ead82cad605ec2b14a1905ad914cc124Magnus Damm .fb_read = fb_sys_read, 20952540c111ead82cad605ec2b14a1905ad914cc124Magnus Damm .fb_write = fb_sys_write, 20968564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm .fb_fillrect = sh_mobile_lcdc_fillrect, 20978564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm .fb_copyarea = sh_mobile_lcdc_copyarea, 20988564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm .fb_imageblit = sh_mobile_lcdc_imageblit, 20998857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot .fb_blank = sh_mobile_lcdc_blank, 2100d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_pan_display = sh_mobile_lcdc_pan, 2101d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_ioctl = sh_mobile_lcdc_ioctl, 2102d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_open = sh_mobile_lcdc_open, 2103d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_release = sh_mobile_lcdc_release, 2104d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_check_var = sh_mobile_lcdc_check_var, 2105d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_set_par = sh_mobile_lcdc_set_par, 2106cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 2107cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2108a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartstatic void 2109a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_unregister(struct sh_mobile_lcdc_chan *ch) 2110a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2111a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->info && ch->info->dev) 2112a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unregister_framebuffer(ch->info); 2113a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2114a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2115a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartstatic int __devinit 2116a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch) 2117a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2118a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_info *info = ch->info; 2119a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart int ret; 2120a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2121a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (info->fbdefio) { 2122a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->sglist = vmalloc(sizeof(struct scatterlist) * 2123a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->fb_size >> PAGE_SHIFT); 2124a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (!ch->sglist) { 2125a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_err(ch->lcdc->dev, "cannot allocate sglist\n"); 2126a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return -ENOMEM; 2127a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2128a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2129a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2130a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->bl_dev = ch->bl; 2131a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2132a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ret = register_framebuffer(info); 2133a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ret < 0) 2134a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2135a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2136a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_info(ch->lcdc->dev, "registered %s/%s as %dx%d %dbpp.\n", 2137b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart dev_name(ch->lcdc->dev), (ch->cfg->chan == LCDC_CHAN_MAINLCD) ? 2138a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart "mainlcd" : "sublcd", info->var.xres, info->var.yres, 2139a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->var.bits_per_pixel); 2140a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2141a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* deferred io mode: disable clock to save power */ 2142a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED) 2143a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart sh_mobile_lcdc_clk_off(ch->lcdc); 2144a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2145a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2146a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2147a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2148a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartstatic void 2149a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch) 2150a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2151a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_info *info = ch->info; 2152a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2153a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (!info || !info->device) 2154a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return; 2155a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2156a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->sglist) 2157a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart vfree(ch->sglist); 2158a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2159a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart fb_dealloc_cmap(&info->cmap); 2160a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart framebuffer_release(info); 2161a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2162a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2163a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartstatic int __devinit 2164a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, 2165a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart const struct fb_videomode *mode, 2166a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unsigned int num_modes) 2167a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2168a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct sh_mobile_lcdc_priv *priv = ch->lcdc; 2169a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_var_screeninfo *var; 2170a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_info *info; 2171a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart int ret; 2172a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2173a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Allocate and initialize the frame buffer device. Create the modes 2174a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart * list and allocate the color map. 2175a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2176a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info = framebuffer_alloc(0, priv->dev); 2177a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (info == NULL) { 2178a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_err(priv->dev, "unable to allocate fb_info\n"); 2179a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return -ENOMEM; 2180a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2181a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2182a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->info = info; 2183a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2184a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->flags = FBINFO_FLAG_DEFAULT; 2185a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fbops = &sh_mobile_lcdc_ops; 2186a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->device = priv->dev; 2187a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->screen_base = ch->fb_mem; 2188a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->pseudo_palette = &ch->pseudo_palette; 2189a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->par = ch; 2190a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2191a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart fb_videomode_to_modelist(mode, num_modes, &info->modelist); 2192a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2193a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); 2194a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ret < 0) { 2195a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_err(priv->dev, "unable to allocate cmap\n"); 2196a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2197a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2198a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2199a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Initialize fixed screen information. Restrict pan to 2 lines steps 2200a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart * for NV12 and NV21. 2201a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2202a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fix = sh_mobile_lcdc_fix; 2203a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fix.smem_start = ch->dma_handle; 2204a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fix.smem_len = ch->fb_size; 220558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.line_length = ch->pitch; 220658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 220758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ch->format->yuv) 220858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 220958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart else 221058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 221158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 2212a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->format->fourcc == V4L2_PIX_FMT_NV12 || 2213a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->format->fourcc == V4L2_PIX_FMT_NV21) 2214a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fix.ypanstep = 2; 2215a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2216a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Initialize variable screen information using the first mode as 2217a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart * default. The default Y virtual resolution is twice the panel size to 2218a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart * allow for double-buffering. 2219a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2220a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var = &info->var; 2221a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart fb_videomode_to_var(var, mode); 2222b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart var->width = ch->cfg->panel_cfg.width; 2223b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart var->height = ch->cfg->panel_cfg.height; 2224a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var->yres_virtual = var->yres * 2; 2225a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var->activate = FB_ACTIVATE_NOW; 2226a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2227a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Use the legacy API by default for RGB formats, and the FOURCC API 2228a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart * for YUV formats. 2229a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2230a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (!ch->format->yuv) 2231a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var->bits_per_pixel = ch->format->bpp; 2232a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart else 2233a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var->grayscale = ch->format->fourcc; 2234a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2235d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart ret = sh_mobile_lcdc_check_var(var, info); 2236a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ret) 2237a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2238a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2239a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return 0; 2240a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2241a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2242f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2243f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Backlight 2244f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2245f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 22463b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) 22473b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 22483b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); 22493b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot int brightness = bdev->props.brightness; 22503b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22513b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot if (bdev->props.power != FB_BLANK_UNBLANK || 22523b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) 22533b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot brightness = 0; 22543b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2255b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart return ch->cfg->bl_info.set_brightness(brightness); 22563b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 22573b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22583b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev) 22593b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 22603b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); 22613b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2262b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart return ch->cfg->bl_info.get_brightness(); 22633b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 22643b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22653b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic int sh_mobile_lcdc_check_fb(struct backlight_device *bdev, 22663b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct fb_info *info) 22673b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 22683b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot return (info->bl_dev == bdev); 22693b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 22703b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22713b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic struct backlight_ops sh_mobile_lcdc_bl_ops = { 22723b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .options = BL_CORE_SUSPENDRESUME, 22733b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .update_status = sh_mobile_lcdc_update_bl, 22743b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .get_brightness = sh_mobile_lcdc_get_brightness, 22753b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .check_fb = sh_mobile_lcdc_check_fb, 22763b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot}; 22773b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22783b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent, 22793b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct sh_mobile_lcdc_chan *ch) 22803b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 22813b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct backlight_device *bl; 22823b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2283b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart bl = backlight_device_register(ch->cfg->bl_info.name, parent, ch, 22843b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot &sh_mobile_lcdc_bl_ops, NULL); 2285beee1f20a185c7e79fd33bb83e04fe44ecd75af3Dan Carpenter if (IS_ERR(bl)) { 2286beee1f20a185c7e79fd33bb83e04fe44ecd75af3Dan Carpenter dev_err(parent, "unable to register backlight device: %ld\n", 2287beee1f20a185c7e79fd33bb83e04fe44ecd75af3Dan Carpenter PTR_ERR(bl)); 22883b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot return NULL; 22893b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot } 22903b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2291b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart bl->props.max_brightness = ch->cfg->bl_info.max_brightness; 22923b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot bl->props.brightness = bl->props.max_brightness; 22933b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_update_status(bl); 22943b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22953b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot return bl; 22963b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 22973b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22983b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev) 22993b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 23003b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_device_unregister(bdev); 23013b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 23023b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2303f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2304f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Power management 2305f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2306f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 23072feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Dammstatic int sh_mobile_lcdc_suspend(struct device *dev) 23082feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm{ 23092feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23102feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23112feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm sh_mobile_lcdc_stop(platform_get_drvdata(pdev)); 23122feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm return 0; 23132feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm} 23142feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23152feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Dammstatic int sh_mobile_lcdc_resume(struct device *dev) 23162feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm{ 23172feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23182feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23192feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm return sh_mobile_lcdc_start(platform_get_drvdata(pdev)); 23202feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm} 23212feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23220246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Dammstatic int sh_mobile_lcdc_runtime_suspend(struct device *dev) 23230246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm{ 23240246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23252427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 23260246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23270246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm /* turn off LCDC hardware */ 23282427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart lcdc_write(priv, _LDCNT1R, 0); 23292427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart 23300246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm return 0; 23310246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm} 23320246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23330246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Dammstatic int sh_mobile_lcdc_runtime_resume(struct device *dev) 23340246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm{ 23350246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23362427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 23370246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23382427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart __sh_mobile_lcdc_start(priv); 23390246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23400246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm return 0; 23410246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm} 23420246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 2343471452104b8520337ae2fb48c4e61cd4896e025dAlexey Dobriyanstatic const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { 23442feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm .suspend = sh_mobile_lcdc_suspend, 23452feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm .resume = sh_mobile_lcdc_resume, 23460246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm .runtime_suspend = sh_mobile_lcdc_runtime_suspend, 23470246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm .runtime_resume = sh_mobile_lcdc_runtime_resume, 23482feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm}; 23492feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 2350f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2351f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Framebuffer notifier 2352f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2353f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 23546de9edd5bde0cdfea12e9948690e53ec669c3018Guennadi Liakhovetski/* locking: called with info->lock held */ 23556011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetskistatic int sh_mobile_lcdc_notify(struct notifier_block *nb, 23566011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski unsigned long action, void *data) 23576011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski{ 23586011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski struct fb_event *event = data; 23596011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski struct fb_info *info = event->info; 23606011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 23616011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 23626011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski if (&ch->lcdc->notifier != nb) 2363baf163749952ca5e33dd2d6a74da023e385c3a00Guennadi Liakhovetski return NOTIFY_DONE; 23646011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 23656011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", 23666011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski __func__, action, event->data); 23676011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 23686011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski switch(action) { 23696011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski case FB_EVENT_SUSPEND: 237037c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_off(ch); 2371afe417c0355154c8b2547619771d6053b3c0aad7Guennadi Liakhovetski sh_mobile_lcdc_stop(ch->lcdc); 23726011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski break; 23736011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski case FB_EVENT_RESUME: 2374dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_lock(&ch->open_lock); 2375dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski sh_mobile_fb_reconfig(info); 2376dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_unlock(&ch->open_lock); 23776011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 237837c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_on(ch); 2379ebe5e12d00f4785092a9650845ad3451bbf4b311Guennadi Liakhovetski sh_mobile_lcdc_start(ch->lcdc); 23806011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski } 23816011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 2382baf163749952ca5e33dd2d6a74da023e385c3a00Guennadi Liakhovetski return NOTIFY_OK; 23836011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski} 23846011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 2385f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2386f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Probe/remove and driver init/exit 2387f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2388f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2389217e9c4353aa86f0c7eeb4c275bca73ea8b53be1Laurent Pinchartstatic const struct fb_videomode default_720p __devinitconst = { 2390f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .name = "HDMI 720p", 2391f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .xres = 1280, 2392f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .yres = 720, 2393f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2394f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .left_margin = 220, 2395f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .right_margin = 110, 2396f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .hsync_len = 40, 2397f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2398f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .upper_margin = 20, 2399f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .lower_margin = 5, 2400f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .vsync_len = 5, 2401f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2402f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .pixclock = 13468, 2403f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .refresh = 60, 2404f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, 2405f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart}; 2406f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2407b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchartstatic int sh_mobile_lcdc_remove(struct platform_device *pdev) 2408b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart{ 2409b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 2410c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int i; 2411b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2412b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart fb_unregister_client(&priv->notifier); 2413b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2414c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) 2415c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]); 2416b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->ch); i++) 2417a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]); 2418b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2419b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart sh_mobile_lcdc_stop(priv); 2420b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2421c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) { 2422c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; 2423c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2424c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_fb_cleanup(ovl); 2425c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2426c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->fb_mem) 2427c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dma_free_coherent(&pdev->dev, ovl->fb_size, 2428c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->fb_mem, ovl->dma_handle); 2429c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2430c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2431b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { 24329a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; 2433b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2434e34d0bbb062cc78802d0f0686c939ea1569889a6Laurent Pinchart if (ch->tx_dev) { 2435e34d0bbb062cc78802d0f0686c939ea1569889a6Laurent Pinchart ch->tx_dev->lcdc = NULL; 2436b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart module_put(ch->cfg->tx_dev->dev.driver->owner); 2437e34d0bbb062cc78802d0f0686c939ea1569889a6Laurent Pinchart } 24389a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart 2439a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart sh_mobile_lcdc_channel_fb_cleanup(ch); 2440b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2441a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->fb_mem) 2442a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dma_free_coherent(&pdev->dev, ch->fb_size, 2443a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->fb_mem, ch->dma_handle); 2444b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart } 2445b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2446b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { 24470c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; 24480c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart 24490c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart if (ch->bl) 24500c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart sh_mobile_lcdc_bl_remove(ch->bl); 24510c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart mutex_destroy(&ch->open_lock); 2452b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart } 2453b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 24544774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart if (priv->dot_clk) { 24554774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart pm_runtime_disable(&pdev->dev); 2456b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart clk_put(priv->dot_clk); 24574774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart } 2458b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2459b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart if (priv->base) 2460b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart iounmap(priv->base); 2461b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2462b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart if (priv->irq) 2463b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart free_irq(priv->irq, priv); 2464b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart kfree(priv); 2465b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart return 0; 2466b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart} 2467cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2468217e9c4353aa86f0c7eeb4c275bca73ea8b53be1Laurent Pinchartstatic int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) 2469f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 2470b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart int interface_type = ch->cfg->interface_type; 2471f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2472f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart switch (interface_type) { 2473f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB8: 2474f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB9: 2475f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB12A: 2476f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB12B: 2477f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB16: 2478f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB18: 2479f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB24: 2480f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8A: 2481f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8B: 2482f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8C: 2483f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8D: 2484f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS9: 2485f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS12: 2486f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS16A: 2487f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS16B: 2488f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS16C: 2489f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS18: 2490f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS24: 2491f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart break; 2492f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart default: 2493f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return -EINVAL; 2494f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 2495f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2496f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart /* SUBLCD only supports SYS interface */ 2497f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (lcdc_chan_is_sublcd(ch)) { 2498f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (!(interface_type & LDMT1R_IFM)) 2499f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return -EINVAL; 2500f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2501f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart interface_type &= ~LDMT1R_IFM; 2502f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 2503f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2504f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart ch->ldmt1r_value = interface_type; 2505f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return 0; 2506f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 2507f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 25080a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchartstatic int __devinit 2509c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv, 2510c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl) 2511c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 2512c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const struct sh_mobile_lcdc_format_info *format; 2513c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int ret; 2514c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2515c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->cfg->fourcc == 0) 2516c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 2517c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2518c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Validate the format. */ 2519c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = sh_mobile_format_info(ovl->cfg->fourcc); 2520c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (format == NULL) { 2521c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dev_err(priv->dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc); 2522c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 2523c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2524c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2525c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->enabled = false; 2526c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->mode = LCDC_OVERLAY_BLEND; 2527c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->alpha = 255; 2528c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->rop3 = 0; 2529c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_x = 0; 2530c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_y = 0; 2531c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2532c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* The default Y virtual resolution is twice the panel size to allow for 2533c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * double-buffering. 2534c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 2535c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->format = format; 2536c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres = ovl->cfg->max_xres; 2537c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres_virtual = ovl->xres; 2538c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres = ovl->cfg->max_yres; 2539c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres_virtual = ovl->yres * 2; 2540c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2541c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!format->yuv) 2542c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pitch = ovl->xres * format->bpp / 8; 2543c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 2544c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pitch = ovl->xres; 2545c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2546c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Allocate frame buffer memory. */ 2547c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres 2548c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * format->bpp / 8 * 2; 2549c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->fb_mem = dma_alloc_coherent(priv->dev, ovl->fb_size, 2550c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart &ovl->dma_handle, GFP_KERNEL); 2551c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!ovl->fb_mem) { 2552c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dev_err(priv->dev, "unable to allocate buffer\n"); 2553c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -ENOMEM; 2554c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2555c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2556c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = sh_mobile_lcdc_overlay_fb_init(ovl); 2557c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 2558c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 2559c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2560c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 2561c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 2562c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2563c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int __devinit 25640a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchartsh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, 25650a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart struct sh_mobile_lcdc_chan *ch) 2566cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 2567105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart const struct sh_mobile_lcdc_format_info *format; 2568b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg; 25693ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart const struct fb_videomode *max_mode; 25703ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart const struct fb_videomode *mode; 2571a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unsigned int num_modes; 25723ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart unsigned int max_size; 2573a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unsigned int i; 25743ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 2575a67472ad1ae040f073e45048cbc5a01195f2e3f5Laurent Pinchart mutex_init(&ch->open_lock); 2576ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart ch->notify = sh_mobile_lcdc_display_notify; 2577a67472ad1ae040f073e45048cbc5a01195f2e3f5Laurent Pinchart 2578105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart /* Validate the format. */ 2579105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart format = sh_mobile_format_info(cfg->fourcc); 2580105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart if (format == NULL) { 2581105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart dev_err(priv->dev, "Invalid FOURCC %08x.\n", cfg->fourcc); 2582105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart return -EINVAL; 2583105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart } 2584105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 25853ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart /* Iterate through the modes to validate them and find the highest 25863ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart * resolution. 25873ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart */ 25883ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_mode = NULL; 25893ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_size = 0; 25903ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 259193ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart for (i = 0, mode = cfg->lcd_modes; i < cfg->num_modes; i++, mode++) { 25923ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart unsigned int size = mode->yres * mode->xres; 25933ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 2594edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart /* NV12/NV21 buffers must have even number of lines */ 2595edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart if ((cfg->fourcc == V4L2_PIX_FMT_NV12 || 2596edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) { 25970a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart dev_err(priv->dev, "yres must be multiple of 2 for " 25980a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart "YCbCr420 mode.\n"); 25993ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart return -EINVAL; 26003ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26013ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 26023ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (size > max_size) { 26033ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_mode = mode; 26043ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_size = size; 26053ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26063ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26073ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 26083ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (!max_size) 26093ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_size = MAX_XRES * MAX_YRES; 26103ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart else 26110a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart dev_dbg(priv->dev, "Found largest videomode %ux%u\n", 26123ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_mode->xres, max_mode->yres); 26133ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 261493ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart if (cfg->lcd_modes == NULL) { 26153ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart mode = &default_720p; 261693ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart num_modes = 1; 26173ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } else { 261893ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart mode = cfg->lcd_modes; 261993ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart num_modes = cfg->num_modes; 26203ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26213ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 262258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart /* Use the first mode as default. */ 262358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->format = format; 262458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres = mode->xres; 262558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres_virtual = mode->xres; 262658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres = mode->yres; 262758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres_virtual = mode->yres * 2; 262858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 262958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (!format->yuv) { 263058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->colorspace = V4L2_COLORSPACE_SRGB; 263158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->pitch = ch->xres * format->bpp / 8; 263258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart } else { 263358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->colorspace = V4L2_COLORSPACE_REC709; 263458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->pitch = ch->xres; 263558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart } 263658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 2637a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->display.width = cfg->panel_cfg.width; 2638a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->display.height = cfg->panel_cfg.height; 2639a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->display.mode = *mode; 2640a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2641a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Allocate frame buffer memory. */ 2642a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->fb_size = max_size * format->bpp / 8 * 2; 2643a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->fb_mem = dma_alloc_coherent(priv->dev, ch->fb_size, &ch->dma_handle, 2644a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart GFP_KERNEL); 2645a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->fb_mem == NULL) { 2646a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_err(priv->dev, "unable to allocate buffer\n"); 2647a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return -ENOMEM; 2648a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 26493ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 265013f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart /* Initialize the transmitter device if present. */ 265113f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart if (cfg->tx_dev) { 265213f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart if (!cfg->tx_dev->dev.driver || 265313f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart !try_module_get(cfg->tx_dev->dev.driver->owner)) { 265413f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart dev_warn(priv->dev, 265513f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart "unable to get transmitter device\n"); 265613f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart return -EINVAL; 265713f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart } 265813f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart ch->tx_dev = platform_get_drvdata(cfg->tx_dev); 265913f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart ch->tx_dev->lcdc = ch; 266013f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart ch->tx_dev->def_mode = *mode; 266113f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart } 266213f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart 2663a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return sh_mobile_lcdc_channel_fb_init(ch, mode, num_modes); 26643ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart} 26653ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 26663ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchartstatic int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) 26673ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart{ 266801ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; 26693ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart struct sh_mobile_lcdc_priv *priv; 2670cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct resource *res; 26713ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart int num_channels; 2672cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int error; 26733ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart int i; 2674cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 267501ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski if (!pdata) { 2676cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "no platform data defined\n"); 26778bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski return -EINVAL; 2678cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2679cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2680cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 26818564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm i = platform_get_irq(pdev, 0); 26828564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm if (!res || i < 0) { 26838564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm dev_err(&pdev->dev, "cannot get platform resources\n"); 26848bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski return -ENOENT; 2685cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2686cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2687cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm priv = kzalloc(sizeof(*priv), GFP_KERNEL); 2688cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!priv) { 2689cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "cannot allocate device data\n"); 26908bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski return -ENOMEM; 2691cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2692cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 26934774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart priv->dev = &pdev->dev; 26944774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart priv->meram_dev = pdata->meram_dev; 26958bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski platform_set_drvdata(pdev, priv); 26968bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski 2697f8798ccbefc0e4ef7438c080b7ba0410738c8cfaYong Zhang error = request_irq(i, sh_mobile_lcdc_irq, 0, 26987ad33e74857f16f1202cbc5746faf52e88e8b376Kay Sievers dev_name(&pdev->dev), priv); 26998564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm if (error) { 27008564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm dev_err(&pdev->dev, "unable to request irq\n"); 27018564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm goto err1; 27028564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm } 27038564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 27048564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm priv->irq = i; 27055ef6b505d9df45558402bdb823a078840a6a26c4Guennadi Liakhovetski atomic_set(&priv->hw_usecnt, -1); 2706cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27073ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) { 27083ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels; 2709cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 271001ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski ch->lcdc = priv; 2711b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart ch->cfg = &pdata->ch[i]; 2712cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 271301ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski error = sh_mobile_lcdc_check_interface(ch); 2714cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) { 2715cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "unsupported interface type\n"); 2716cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2717cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 271801ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski init_waitqueue_head(&ch->frame_end_wait); 271901ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski init_completion(&ch->vsync_completion); 272001ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski ch->pan_offset = 0; 2721cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27223b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot /* probe the backlight is there is one defined */ 2723b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart if (ch->cfg->bl_info.max_brightness) 27243b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch); 27253b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2726cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm switch (pdata->ch[i].chan) { 2727cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm case LCDC_CHAN_MAINLCD: 2728ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart ch->enabled = LDCNT2R_ME; 272901ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski ch->reg_offs = lcdc_offs_mainlcd; 27303ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart num_channels++; 2731cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 2732cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm case LCDC_CHAN_SUBLCD: 2733ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart ch->enabled = LDCNT2R_SE; 273401ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski ch->reg_offs = lcdc_offs_sublcd; 27353ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart num_channels++; 2736cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 2737cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2738cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2739cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27403ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (!num_channels) { 2741cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "no channels defined\n"); 2742cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm error = -EINVAL; 2743cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2744cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2745cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2746edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart /* for dual channel LCDC (MAIN + SUB) force shared format setting */ 27473ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (num_channels == 2) 2748edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart priv->forced_fourcc = pdata->ch[0].fourcc; 2749417d48274e755e537bae60461558c1f63a4e14deMagnus Damm 2750dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski priv->base = ioremap_nocache(res->start, resource_size(res)); 2751dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski if (!priv->base) 2752dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski goto err1; 2753dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski 27540a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart error = sh_mobile_lcdc_setup_clocks(priv, pdata->clock_source); 2755cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) { 2756cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "unable to setup clocks\n"); 2757cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2758cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2759cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27604774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart /* Enable runtime PM. */ 27614774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart pm_runtime_enable(&pdev->dev); 27627caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 27633ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart for (i = 0; i < num_channels; i++) { 276401ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = priv->ch + i; 2765c44f9f76d26c3b5158c65201d30e96393efe2fbdGuennadi Liakhovetski 27660a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart error = sh_mobile_lcdc_channel_init(priv, ch); 2767cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) 27683ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart goto err1; 2769cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2770cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2771c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { 2772c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; 2773c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2774c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->cfg = &pdata->overlays[i]; 2775c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->channel = &priv->ch[0]; 2776c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2777c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart error = sh_mobile_lcdc_overlay_init(priv, ovl); 2778c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (error) 2779c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart goto err1; 2780c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2781c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2782cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm error = sh_mobile_lcdc_start(priv); 2783cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) { 2784cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "unable to start hardware\n"); 2785cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2786cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2787cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27883ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart for (i = 0; i < num_channels; i++) { 27891c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt struct sh_mobile_lcdc_chan *ch = priv->ch + i; 27901c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt 2791a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart error = sh_mobile_lcdc_channel_fb_register(ch); 2792a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (error) 2793cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2794cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2795cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2796c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { 2797c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; 2798c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2799c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart error = sh_mobile_lcdc_overlay_fb_register(ovl); 2800c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (error) 2801c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart goto err1; 2802c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2803c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 28046011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* Failure ignored */ 28056011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski priv->notifier.notifier_call = sh_mobile_lcdc_notify; 28066011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski fb_register_client(&priv->notifier); 28076011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 2808cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return 0; 28098bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetskierr1: 2810cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm sh_mobile_lcdc_remove(pdev); 28118bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski 2812cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return error; 2813cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 2814cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2815cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic struct platform_driver sh_mobile_lcdc_driver = { 2816cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .driver = { 2817cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .name = "sh_mobile_lcdc_fb", 2818cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .owner = THIS_MODULE, 28192feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm .pm = &sh_mobile_lcdc_dev_pm_ops, 2820cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm }, 2821cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .probe = sh_mobile_lcdc_probe, 2822cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .remove = sh_mobile_lcdc_remove, 2823cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 2824cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 28254277f2c4667187cbbdd3da3be31ee681bc6b8300Axel Linmodule_platform_driver(sh_mobile_lcdc_driver); 2826cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2827cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus DammMODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver"); 2828cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus DammMODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); 2829cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus DammMODULE_LICENSE("GPL v2"); 2830