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) 164a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart * @pan_y_offset: Panning linear offset in bytes (luma component) 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; 194a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned long pan_y_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) 347deccd24f9077ccabc6b34f2e6d2f75c98b528fa1Laurent Pinchart clk_prepare_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) 361deccd24f9077ccabc6b34f2e6d2f75c98b528fa1Laurent Pinchart clk_disable_unprepare(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 441d38d840ac61fdd5fe86b3b5925f538b0a26ed85bLaurent Pinchartstatic struct 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 */ 5773a41c5dbe8bc396a7fb16ca8739e945bb003342eGu Zheng console_lock(); 578ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart if (lock_fb_info(info)) { 5793a41c5dbe8bc396a7fb16ca8739e945bb003342eGu Zheng 580ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 5812d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.width = monspec->max_x * 10; 5822d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.height = monspec->max_y * 10; 583e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart 584e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart if (!sh_mobile_lcdc_must_reconfigure(ch, mode) && 585ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart info->state == FBINFO_STATE_RUNNING) { 586ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* First activation with the default monitor. 587ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart * Just turn on, if we run a resume here, the 588ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart * logo disappears. 589ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart */ 590856e8dfe6efed7cf35bc6bf827f030a164bee083Laurent Pinchart info->var.width = ch->display.width; 591856e8dfe6efed7cf35bc6bf827f030a164bee083Laurent Pinchart info->var.height = ch->display.height; 592ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart sh_mobile_lcdc_display_on(ch); 593ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } else { 594ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* New monitor or have to wake up */ 595ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart fb_set_suspend(info, 0); 596ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 597ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 5983a41c5dbe8bc396a7fb16ca8739e945bb003342eGu Zheng 599ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart unlock_fb_info(info); 600ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 6013a41c5dbe8bc396a7fb16ca8739e945bb003342eGu Zheng console_unlock(); 602ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart break; 603ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 604ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT: 605ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* HDMI disconnect */ 6063a41c5dbe8bc396a7fb16ca8739e945bb003342eGu Zheng console_lock(); 607ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart if (lock_fb_info(info)) { 608ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart fb_set_suspend(info, 1); 609ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart unlock_fb_info(info); 610ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 6113a41c5dbe8bc396a7fb16ca8739e945bb003342eGu Zheng console_unlock(); 612ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart break; 613ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 614ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE: 615ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* Validate a proposed new mode */ 616e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart fb_videomode_to_var(&var, mode); 617e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart var.bits_per_pixel = info->var.bits_per_pixel; 618e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart var.grayscale = info->var.grayscale; 619d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart ret = sh_mobile_lcdc_check_var(&var, info); 620ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart break; 621ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 622ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 623ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart return ret; 624ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart} 625ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 626f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 627f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Format helpers 628f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 629f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 630105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartstruct sh_mobile_lcdc_format_info { 631105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart u32 fourcc; 632105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart unsigned int bpp; 633105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart bool yuv; 634105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart u32 lddfr; 635105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart}; 636105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 637105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartstatic const struct sh_mobile_lcdc_format_info sh_mobile_format_infos[] = { 638105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart { 639105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_RGB565, 640105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 16, 641105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = false, 642105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_PKF_RGB16, 643105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 644105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_BGR24, 645105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 24, 646105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = false, 647105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_PKF_RGB24, 648105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 649105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_BGR32, 650105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 32, 651105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = false, 652105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_PKF_ARGB32, 653105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 654105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV12, 655105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 12, 656105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 657105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_420, 658105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 659105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV21, 660105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 12, 661105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 662105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_420, 663105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 664105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV16, 665105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 16, 666105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 667105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_422, 668105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 669105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV61, 670105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 16, 671105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 672105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_422, 673105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 674105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV24, 675105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 24, 676105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 677105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_444, 678105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 679105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV42, 680105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 24, 681105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 682105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_444, 683105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, 684105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart}; 685105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 686105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartstatic const struct sh_mobile_lcdc_format_info * 687105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartsh_mobile_format_info(u32 fourcc) 688105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart{ 689105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart unsigned int i; 690105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 691105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart for (i = 0; i < ARRAY_SIZE(sh_mobile_format_infos); ++i) { 692105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart if (sh_mobile_format_infos[i].fourcc == fourcc) 693105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart return &sh_mobile_format_infos[i]; 694105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart } 695105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 696105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart return NULL; 697105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart} 698105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 699f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var) 700f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 701f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (var->grayscale > 1) 702f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return var->grayscale; 703f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 704f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart switch (var->bits_per_pixel) { 705f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case 16: 706f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return V4L2_PIX_FMT_RGB565; 707f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case 24: 708f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return V4L2_PIX_FMT_BGR24; 709f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case 32: 710f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return V4L2_PIX_FMT_BGR32; 711f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart default: 712f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return 0; 713f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 714f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 715f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 716f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var) 717f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 718f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return var->grayscale > 1; 719f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 720f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 721f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 722f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Start, stop and IRQ 723f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 724f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 7258564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) 7268564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 7278564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm struct sh_mobile_lcdc_priv *priv = data; 7282feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm struct sh_mobile_lcdc_chan *ch; 7299dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy unsigned long ldintr; 7302feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm int is_sub; 7312feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm int k; 7328564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 733dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart /* Acknowledge interrupts and disable further VSYNC End IRQs. */ 734dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart ldintr = lcdc_read(priv, _LDINTR); 735dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE); 7368564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 7372feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm /* figure out if this interrupt is for main or sub lcd */ 738ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0; 7392feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7409dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy /* wake up channel and disable clocks */ 7412feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 7422feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm ch = &priv->ch[k]; 7432feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7442feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm if (!ch->enabled) 7452feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm continue; 7462feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 747dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart /* Frame End */ 7489dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy if (ldintr & LDINTR_FS) { 7499dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy if (is_sub == lcdc_chan_is_sublcd(ch)) { 7509dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy ch->frame_end = 1; 7519dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy wake_up(&ch->frame_end_wait); 7522feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7539dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy sh_mobile_lcdc_clk_off(priv); 7549dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy } 7559dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy } 7569dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 7579dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy /* VSYNC End */ 75840331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy if (ldintr & LDINTR_VES) 75940331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy complete(&ch->vsync_completion); 7602feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm } 7612feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7628564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm return IRQ_HANDLED; 7638564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 7648564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 765d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_wait_for_vsync(struct sh_mobile_lcdc_chan *ch) 7664976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart{ 7674976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart unsigned long ldintr; 7684976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart int ret; 7694976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 7704976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart /* Enable VSync End interrupt and be careful not to acknowledge any 7714976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart * pending interrupt. 7724976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart */ 7734976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart ldintr = lcdc_read(ch->lcdc, _LDINTR); 7744976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK; 7754976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart lcdc_write(ch->lcdc, _LDINTR, ldintr); 7764976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 7774976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion, 7784976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart msecs_to_jiffies(100)); 7794976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart if (!ret) 7804976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart return -ETIMEDOUT; 7814976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 7824976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart return 0; 7834976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart} 7844976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 785cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv, 786cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int start) 787cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 788cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long tmp = lcdc_read(priv, _LDCNT2R); 789cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int k; 790cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 791cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* start or stop the lcdc */ 792cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (start) 793ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO); 794cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm else 795ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO); 796cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 797cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* wait until power is applied/stopped on all channels */ 798cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) 799cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled) 800cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm while (1) { 801ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart tmp = lcdc_read_chan(&priv->ch[k], LDPMR) 802ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart & LDPMR_LPS; 803ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart if (start && tmp == LDPMR_LPS) 804cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 805cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!start && tmp == 0) 806cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 807cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm cpu_relax(); 808cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 809cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 810cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!start) 811cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */ 812cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 813cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 8146011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetskistatic void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) 8156011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski{ 8162d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart const struct fb_var_screeninfo *var = &ch->info->var; 8172d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart const struct fb_videomode *mode = &ch->display.mode; 8181c120deb60edd4c19a2109daa98f65f2ad3b9c06Guennadi Liakhovetski unsigned long h_total, hsync_pos, display_h_total; 8196011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski u32 tmp; 8206011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8216011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski tmp = ch->ldmt1r_value; 822ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL; 823ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL; 824b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0; 825b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0; 826b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0; 827b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0; 828b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0; 8296011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDMT1R, tmp); 8306011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8316011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* setup SYS bus */ 832b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart lcdc_write_chan(ch, LDMT2R, ch->cfg->sys_bus_cfg.ldmt2r); 833b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart lcdc_write_chan(ch, LDMT3R, ch->cfg->sys_bus_cfg.ldmt3r); 8346011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8356011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* horizontal configuration */ 8362d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart h_total = mode->xres + mode->hsync_len + mode->left_margin 8372d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart + mode->right_margin; 8386011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski tmp = h_total / 8; /* HTCN */ 83958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */ 8406011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDHCNR, tmp); 8416011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8422d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart hsync_pos = mode->xres + mode->right_margin; 8436011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski tmp = hsync_pos / 8; /* HSYNP */ 8442d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp |= (mode->hsync_len / 8) << 16; /* HSYNW */ 8456011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDHSYNR, tmp); 8466011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8476011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* vertical configuration */ 8482d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp = mode->yres + mode->vsync_len + mode->upper_margin 8492d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart + mode->lower_margin; /* VTLN */ 85058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */ 8516011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDVLNR, tmp); 8526011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8532d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp = mode->yres + mode->lower_margin; /* VSYNP */ 8542d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp |= mode->vsync_len << 16; /* VSYNW */ 8556011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDVSYNR, tmp); 8566011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8576011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* Adjust horizontal synchronisation for HDMI */ 8582d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart display_h_total = mode->xres + mode->hsync_len + mode->left_margin 8592d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart + mode->right_margin; 8602d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16) 8612d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7); 8626011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDHAJR, tmp); 8639beb09f1cadf33145c307c504f844ae24686c872Kuninori Morimoto lcdc_write_chan_mirror(ch, LDHAJR, tmp); 8646011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski} 8656011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 866c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl) 867c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 868c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart u32 format = 0; 869c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 870c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!ovl->enabled) { 871c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); 872c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0); 873c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, 874c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); 875c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return; 876c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 877c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 878c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->base_addr_y = ovl->dma_handle; 879a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ovl->base_addr_c = ovl->dma_handle 880a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + ovl->xres_virtual * ovl->yres_virtual; 881c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 882c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (ovl->mode) { 883c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case LCDC_OVERLAY_BLEND: 884c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT); 885c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 886c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 887c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case LCDC_OVERLAY_ROP3: 888c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = LDBBSIFR_EN | LDBBSIFR_BRSEL 889c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT); 890c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 891c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 892c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 893c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (ovl->format->fourcc) { 894c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_RGB565: 895c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV21: 896c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV61: 897c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV42: 898c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW; 899c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 900c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR24: 901c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV12: 902c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV16: 903c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV24: 904c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB; 905c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 906c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR32: 907c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart default: 908c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_SWPL; 909c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 910c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 911c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 912c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (ovl->format->fourcc) { 913c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_RGB565: 914c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16; 915c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 916c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR24: 917c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24; 918c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 919c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR32: 920c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32; 921c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 922c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV12: 923c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV21: 924c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420; 925c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 926c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV16: 927c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV61: 928c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422; 929c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 930c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV24: 931c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV42: 932c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444; 933c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 934c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 935c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 936c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); 937c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 938c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format); 939c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 940c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index), 941c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->yres << LDBBSSZR_BVSS_SHIFT) | 942c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->xres << LDBBSSZR_BHSS_SHIFT)); 943c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index), 944c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->pos_y << LDBBLOCR_CVLC_SHIFT) | 945c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->pos_x << LDBBLOCR_CHLC_SHIFT)); 946c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index), 947c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pitch << LDBBSMWR_BSMW_SHIFT); 948c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 949c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); 950c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); 951c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 952c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, 953c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); 954c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 955c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 9569a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart/* 957d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart * __sh_mobile_lcdc_start - Configure and start the LCDC 9589a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * @priv: LCDC device 9599a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * 9609a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * Configure all enabled channels and start the LCDC device. All external 9619a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * devices (clocks, MERAM, panels, ...) are not touched by this function. 9629a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 9639a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchartstatic void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 964cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 965cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch; 966cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long tmp; 9679a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int k, m; 9688564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 9699a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Enable LCDC channels. Read data from external memory, avoid using the 9709a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * BEU for now. 9719a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 9729a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled); 973cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 9749a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Stop the LCDC first and disable all interrupts. */ 975cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm sh_mobile_lcdc_start_stop(priv, 0); 9769a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDINTR, 0); 977cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 9789a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Configure power supply, dot clocks and start them. */ 979cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm tmp = priv->lddckr; 980cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 981cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 9829a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (!ch->enabled) 983cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm continue; 984cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 9859a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Power supply */ 9869a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDPMR, 0); 9879a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 988b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart m = ch->cfg->clock_divider; 989cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!m) 990cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm continue; 991cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 992505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider 993505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart * denominator. 994505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart */ 995505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart lcdc_write_chan(ch, LDDCKPAT1R, 0); 996505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); 997505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart 998cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (m == 1) 999ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart m = LDDCKR_MOSEL; 1000cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); 1001cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 1002cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1003cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_write(priv, _LDDCKR, tmp); 1004cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_write(priv, _LDDCKSTPR, 0); 1005cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0); 1006cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10079a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Setup geometry, format, frame buffer memory and operation mode. */ 1008cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1009cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 1010cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!ch->enabled) 1011cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm continue; 1012cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10136011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski sh_mobile_lcdc_geometry(ch); 1014cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1015fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart tmp = ch->format->lddfr; 1016edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart 1017fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart if (ch->format->yuv) { 101858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart switch (ch->colorspace) { 1019edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_COLORSPACE_REC709: 1020edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp |= LDDFR_CF1; 102153b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia break; 1022edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_COLORSPACE_JPEG: 1023edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp |= LDDFR_CF0; 102453b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia break; 102553b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia } 1026417d48274e755e537bae60461558c1f63a4e14deMagnus Damm } 10277caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10289a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDDFR, tmp); 102972c04af9a2d57b7945cf3de8e71461bd80695d50Laurent Pinchart lcdc_write_chan(ch, LDMLSR, ch->line_size); 10309a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); 1031fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart if (ch->format->yuv) 10329a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); 10337caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10349a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* When using deferred I/O mode, configure the LCDC for one-shot 10359a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * operation and enable the frame end interrupt. Otherwise use 10369a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * continuous read mode. 10379a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 10389a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (ch->ldmt1r_value & LDMT1R_IFM && 1039b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart ch->cfg->sys_bus_cfg.deferred_io_msec) { 10409a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSM1R, LDSM1R_OS); 10419a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDINTR, LDINTR_FE); 10429a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } else { 10439a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSM1R, 0); 10449a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10459a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10467caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10479a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Word and long word swap. */ 1048fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart switch (priv->ch[0].format->fourcc) { 1049edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_RGB565: 1050edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV21: 1051edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV61: 1052edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV42: 1053edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp = LDDDSR_LS | LDDDSR_WS; 1054edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1055edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR24: 1056edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV12: 1057edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV16: 1058edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV24: 10599a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS; 1060edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1061edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR32: 1062edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart default: 1063edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp = LDDDSR_LS; 1064edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 10659a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10669a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDDDSR, tmp); 10677caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10689a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Enable the display output. */ 10699a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDCNT1R, LDCNT1R_DE); 10709a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart sh_mobile_lcdc_start_stop(priv, 1); 10719a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart priv->started = 1; 10729a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart} 1073cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10749a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchartstatic int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 10759a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart{ 10769a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart struct sh_mobile_meram_info *mdev = priv->meram_dev; 10779a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart struct sh_mobile_lcdc_chan *ch; 10789a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart unsigned long tmp; 10799a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int ret; 10809a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int k; 1081cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10829a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* enable clocks before accessing the hardware */ 10839a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 10849a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (priv->ch[k].enabled) 10859a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart sh_mobile_lcdc_clk_on(priv); 10869a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10878564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 10889a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* reset */ 10899a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR); 10909a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0); 10918564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 10929a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1093b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_panel_cfg *panel; 10948564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 109537c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart ch = &priv->ch[k]; 10969a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (!ch->enabled) 10979a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart continue; 10989a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 1099b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart panel = &ch->cfg->panel_cfg; 1100afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart if (panel->setup_sys) { 1101afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart ret = panel->setup_sys(ch, &sh_mobile_lcdc_sys_bus_ops); 11029a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (ret) 11039a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart return ret; 11048564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm } 1105cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 1106cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 11079a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Compute frame buffer base address and pitch for each channel. */ 11089a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 11099a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int pixelformat; 11104a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart void *cache; 1111cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 11129a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch = &priv->ch[k]; 11139a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (!ch->enabled) 11149a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart continue; 1115cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 111658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->base_addr_y = ch->dma_handle; 1117a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ch->base_addr_c = ch->dma_handle 1118a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + ch->xres_virtual * ch->yres_virtual; 111972c04af9a2d57b7945cf3de8e71461bd80695d50Laurent Pinchart ch->line_size = ch->pitch; 11209a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11219a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Enable MERAM if possible. */ 11226e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart if (mdev == NULL || ch->cfg->meram_cfg == NULL) 11239a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart continue; 11249a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11254a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart /* Free the allocated MERAM cache. */ 11264a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart if (ch->cache) { 11276e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_free(mdev, ch->cache); 11284a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart ch->cache = NULL; 11299a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 11309a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 1131fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart switch (ch->format->fourcc) { 1132edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV12: 1133edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV21: 1134edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV16: 1135edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV61: 11369a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart pixelformat = SH_MOBILE_MERAM_PF_NV; 1137edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1138edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV24: 1139edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV42: 1140edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart pixelformat = SH_MOBILE_MERAM_PF_NV24; 1141edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1142edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_RGB565: 1143edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR24: 1144edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR32: 1145edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart default: 1146edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart pixelformat = SH_MOBILE_MERAM_PF_RGB; 1147edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1148edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart } 11499a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11506e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg, 1151b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart ch->pitch, ch->yres, pixelformat, 115272c04af9a2d57b7945cf3de8e71461bd80695d50Laurent Pinchart &ch->line_size); 11534a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart if (!IS_ERR(cache)) { 11546e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_update(mdev, cache, 115597d16fe69b6499a14a0c85c053f7bef54ce992a4Laurent Pinchart ch->base_addr_y, ch->base_addr_c, 115697d16fe69b6499a14a0c85c053f7bef54ce992a4Laurent Pinchart &ch->base_addr_y, &ch->base_addr_c); 11574a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart ch->cache = cache; 115897d16fe69b6499a14a0c85c053f7bef54ce992a4Laurent Pinchart } 11599a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 11609a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 1161c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) { 1162c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k]; 1163c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1164c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1165c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 11669a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Start the LCDC. */ 11679a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart __sh_mobile_lcdc_start(priv); 11689a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11699a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Setup deferred I/O, tell the board code to enable the panels, and 11709a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * turn backlight on. 11719a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 1172cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1173cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 117421bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm if (!ch->enabled) 117521bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm continue; 117621bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm 1177b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp = ch->cfg->sys_bus_cfg.deferred_io_msec; 11789a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (ch->ldmt1r_value & LDMT1R_IFM && tmp) { 11799a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; 11809a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch->defio.delay = msecs_to_jiffies(tmp); 11819a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch->info->fbdefio = &ch->defio; 11829a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart fb_deferred_io_init(ch->info); 11839a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 11849a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 118537c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_on(ch); 11863b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 11873b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot if (ch->bl) { 11883b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot ch->bl->props.power = FB_BLANK_UNBLANK; 11893b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_update_status(ch->bl); 11903b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot } 1191cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 1192cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1193cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return 0; 1194cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 1195cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1196cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) 1197cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 1198cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch; 1199cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int k; 1200cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 12012feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm /* clean up deferred io and ask board code to disable panel */ 1202cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1203cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 120421bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm if (!ch->enabled) 120521bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm continue; 12068564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 12072feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm /* deferred io mode: 12082feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm * flush frame, and wait for frame end interrupt 12092feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm * clean up deferred io and enable clock 12102feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm */ 12115ef6b505d9df45558402bdb823a078840a6a26c4Guennadi Liakhovetski if (ch->info && ch->info->fbdefio) { 12122feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm ch->frame_end = 0; 1213e33afddca174171a68d57476ead8947476ab9240Paul Mundt schedule_delayed_work(&ch->info->deferred_work, 0); 12142feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm wait_event(ch->frame_end_wait, ch->frame_end); 1215e33afddca174171a68d57476ead8947476ab9240Paul Mundt fb_deferred_io_cleanup(ch->info); 1216e33afddca174171a68d57476ead8947476ab9240Paul Mundt ch->info->fbdefio = NULL; 12172feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm sh_mobile_lcdc_clk_on(priv); 12188564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm } 12192feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 12203b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot if (ch->bl) { 12213b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot ch->bl->props.power = FB_BLANK_POWERDOWN; 12223b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_update_status(ch->bl); 12233b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot } 12243b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 122537c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_off(ch); 12267caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 12274a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart /* Free the MERAM cache. */ 12284a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart if (ch->cache) { 12296e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_free(priv->meram_dev, ch->cache); 123040af1eb5a73c16fc8270d45b8c37e3c75f107eb4Laurent Pinchart ch->cache = NULL; 12317caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia } 12327caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 1233cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 1234cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1235cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* stop the lcdc */ 12368e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm if (priv->started) { 12378e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm sh_mobile_lcdc_start_stop(priv, 0); 12388e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm priv->started = 0; 12398e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm } 1240b51339fff240ff179730f8963a758147fd60f3ecMagnus Damm 12418564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm /* stop clocks */ 12428564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) 12438564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm if (priv->ch[k].enabled) 12448564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_clk_off(priv); 1245cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 1246cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1247c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, 1248c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info) 1249c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1250c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->xres > MAX_XRES || var->yres > MAX_YRES) 1251c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1252c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1253c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Make sure the virtual resolution is at least as big as the visible 1254c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * resolution. 1255c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1256c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->xres_virtual < var->xres) 1257c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->xres_virtual = var->xres; 1258c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->yres_virtual < var->yres) 1259c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->yres_virtual = var->yres; 1260c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1261c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (sh_mobile_format_is_fourcc(var)) { 1262c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const struct sh_mobile_lcdc_format_info *format; 1263c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1264c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = sh_mobile_format_info(var->grayscale); 1265c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (format == NULL) 1266c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1267c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = format->bpp; 1268c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1269c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Default to RGB and JPEG color-spaces for RGB and YUV formats 1270c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * respectively. 1271c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1272c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!format->yuv) 1273c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->colorspace = V4L2_COLORSPACE_SRGB; 1274c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else if (var->colorspace != V4L2_COLORSPACE_REC709) 1275c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->colorspace = V4L2_COLORSPACE_JPEG; 1276c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else { 1277c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->bits_per_pixel <= 16) { /* RGB 565 */ 1278c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = 16; 1279c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.offset = 11; 1280c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.length = 5; 1281c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.offset = 5; 1282c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.length = 6; 1283c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.offset = 0; 1284c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.length = 5; 1285c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.offset = 0; 1286c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.length = 0; 1287c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ 1288c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = 24; 1289c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.offset = 16; 1290c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.length = 8; 1291c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.offset = 8; 1292c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.length = 8; 1293c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.offset = 0; 1294c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.length = 8; 1295c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.offset = 0; 1296c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.length = 0; 1297c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ 1298c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = 32; 1299c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.offset = 16; 1300c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.length = 8; 1301c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.offset = 8; 1302c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.length = 8; 1303c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.offset = 0; 1304c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.length = 8; 1305c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.offset = 24; 1306c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.length = 8; 1307c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else 1308c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1309c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1310c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.msb_right = 0; 1311c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.msb_right = 0; 1312c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.msb_right = 0; 1313c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.msb_right = 0; 1314c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1315c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1316c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Make sure we don't exceed our allocated memory. */ 1317c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > 1318c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.smem_len) 1319c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1320c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1321c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1322c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1323c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1324c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart/* ----------------------------------------------------------------------------- 1325c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * Frame buffer operations - Overlays 1326c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1327c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1328c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1329c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf) 1330c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1331c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1332c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1333c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1334c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->alpha); 1335c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1336c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1337c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1338c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_alpha_store(struct device *dev, struct device_attribute *attr, 1339c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1340c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1341c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1342c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1343c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int alpha; 1344c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1345c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1346c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart alpha = simple_strtoul(buf, &endp, 10); 1347c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1348c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1349c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1350c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1351c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1352c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1353c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (alpha > 255) 1354c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1355c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1356c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->alpha != alpha) { 1357c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->alpha = alpha; 1358c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1359c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled) 1360c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1361c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1362c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1363c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1364c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1365c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1366c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1367c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_mode_show(struct device *dev, struct device_attribute *attr, char *buf) 1368c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1369c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1370c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1371c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1372c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->mode); 1373c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1374c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1375c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1376c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_mode_store(struct device *dev, struct device_attribute *attr, 1377c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1378c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1379c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1380c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1381c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int mode; 1382c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1383c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1384c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart mode = simple_strtoul(buf, &endp, 10); 1385c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1386c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1387c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1388c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1389c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1390c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1391c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (mode != LCDC_OVERLAY_BLEND && mode != LCDC_OVERLAY_ROP3) 1392c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1393c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1394c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->mode != mode) { 1395c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->mode = mode; 1396c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1397c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->enabled) 1398c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1399c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1400c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1401c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1402c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1403c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1404c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1405c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_position_show(struct device *dev, struct device_attribute *attr, 1406c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *buf) 1407c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1408c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1409c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1410c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1411c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%d,%d\n", ovl->pos_x, ovl->pos_y); 1412c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1413c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1414c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1415c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_position_store(struct device *dev, struct device_attribute *attr, 1416c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1417c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1418c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1419c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1420c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1421c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int pos_x; 1422c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int pos_y; 1423c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1424c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart pos_x = simple_strtol(buf, &endp, 10); 1425c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (*endp != ',') 1426c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1427c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1428c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart pos_y = simple_strtol(endp + 1, &endp, 10); 1429c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1430c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1431c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1432c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1433c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1434c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1435c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) { 1436c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_x = pos_x; 1437c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_y = pos_y; 1438c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1439c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->enabled) 1440c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1441c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1442c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1443c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1444c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1445c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1446c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1447c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_rop3_show(struct device *dev, struct device_attribute *attr, char *buf) 1448c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1449c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1450c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1451c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1452c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->rop3); 1453c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1454c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1455c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1456c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_rop3_store(struct device *dev, struct device_attribute *attr, 1457c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1458c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1459c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1460c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1461c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int rop3; 1462c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1463c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1464c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart rop3 = !!simple_strtoul(buf, &endp, 10); 1465c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1466c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1467c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1468c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1469c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1470c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1471c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (rop3 > 255) 1472c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1473c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1474c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->rop3 != rop3) { 1475c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->rop3 = rop3; 1476c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1477c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled) 1478c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1479c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1480c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1481c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1482c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1483c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1484c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic const struct device_attribute overlay_sysfs_attrs[] = { 1485c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_alpha, S_IRUGO|S_IWUSR, 1486c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_alpha_show, overlay_alpha_store), 1487c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_mode, S_IRUGO|S_IWUSR, 1488c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_mode_show, overlay_mode_store), 1489c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_position, S_IRUGO|S_IWUSR, 1490c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_position_show, overlay_position_store), 1491c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_rop3, S_IRUGO|S_IWUSR, 1492c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_rop3_show, overlay_rop3_store), 1493c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 1494c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1495c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = { 1496c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .id = "SH Mobile LCDC", 1497c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .type = FB_TYPE_PACKED_PIXELS, 1498c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .visual = FB_VISUAL_TRUECOLOR, 1499c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .accel = FB_ACCEL_NONE, 150015dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart .xpanstep = 1, 1501c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .ypanstep = 1, 1502c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .ywrapstep = 0, 1503c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .capabilities = FB_CAP_FOURCC, 1504c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 1505c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1506c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var, 1507c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info) 1508c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1509c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1510c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base_addr_y; 1511c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base_addr_c; 1512a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned long y_offset; 1513c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long c_offset; 1514c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1515a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart if (!ovl->format->yuv) { 1516a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart y_offset = (var->yoffset * ovl->xres_virtual + var->xoffset) 1517a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart * ovl->format->bpp / 8; 1518a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart c_offset = 0; 1519a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart } else { 1520a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned int xsub = ovl->format->bpp < 24 ? 2 : 1; 1521a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned int ysub = ovl->format->bpp < 16 ? 2 : 1; 1522a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart 1523a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart y_offset = var->yoffset * ovl->xres_virtual + var->xoffset; 1524a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart c_offset = var->yoffset / ysub * ovl->xres_virtual * 2 / xsub 1525a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + var->xoffset * 2 / xsub; 1526a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart } 1527c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1528a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart /* If the Y offset hasn't changed, the C offset hasn't either. There's 1529a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart * nothing to do in that case. 1530a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart */ 1531a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart if (y_offset == ovl->pan_y_offset) 1532a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart return 0; 1533c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1534c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Set the source address for the next refresh */ 1535a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart base_addr_y = ovl->dma_handle + y_offset; 1536a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart base_addr_c = ovl->dma_handle + ovl->xres_virtual * ovl->yres_virtual 1537a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + c_offset; 1538c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1539c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->base_addr_y = base_addr_y; 1540a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ovl->base_addr_c = base_addr_c; 1541a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ovl->pan_y_offset = y_offset; 1542c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 15438be7c66995bf06769dc4c5f7a62f3cd62a627e7eLaurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); 15448be7c66995bf06769dc4c5f7a62f3cd62a627e7eLaurent Pinchart 1545c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); 1546c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); 1547c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 15488be7c66995bf06769dc4c5f7a62f3cd62a627e7eLaurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, 15498be7c66995bf06769dc4c5f7a62f3cd62a627e7eLaurent Pinchart LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); 15508be7c66995bf06769dc4c5f7a62f3cd62a627e7eLaurent Pinchart 1551c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1552c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1553c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1554c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_ioctl(struct fb_info *info, unsigned int cmd, 1555c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long arg) 1556c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1557c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1558c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1559c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (cmd) { 1560c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case FBIO_WAITFORVSYNC: 1561c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return sh_mobile_lcdc_wait_for_vsync(ovl->channel); 1562c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1563c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart default: 1564c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -ENOIOCTLCMD; 1565c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1566c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1567c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1568c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_check_var(struct fb_var_screeninfo *var, 1569c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info) 1570c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1571c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return __sh_mobile_lcdc_check_var(var, info); 1572c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1573c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1574c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_set_par(struct fb_info *info) 1575c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1576c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1577c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1578c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->format = 1579c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_format_info(sh_mobile_format_fourcc(&info->var)); 1580c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1581c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres = info->var.xres; 1582c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres_virtual = info->var.xres_virtual; 1583c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres = info->var.yres; 1584c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres_virtual = info->var.yres_virtual; 1585c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1586c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->format->yuv) 158716ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ovl->pitch = info->var.xres_virtual; 1588c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 158916ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ovl->pitch = info->var.xres_virtual * ovl->format->bpp / 8; 1590c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1591c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1592c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1593c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.line_length = ovl->pitch; 1594c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1595c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (sh_mobile_format_is_fourcc(&info->var)) { 1596c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.type = FB_TYPE_FOURCC; 1597c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 1598c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else { 1599c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.type = FB_TYPE_PACKED_PIXELS; 1600c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 1601c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1602c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1603c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1604c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1605c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1606c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart/* Overlay blanking. Disable the overlay when blanked. */ 1607c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info) 1608c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1609c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1610c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1611c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->enabled = !blank; 1612c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1613c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1614c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Prevent the backlight from receiving a blanking event by returning 1615c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * a non-zero value. 1616c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1617c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 1; 1618c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1619c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1620bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKUstatic int 1621bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKUsh_mobile_lcdc_overlay_mmap(struct fb_info *info, struct vm_area_struct *vma) 1622bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU{ 1623bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU struct sh_mobile_lcdc_overlay *ovl = info->par; 1624bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU 1625bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem, 1626bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU ovl->dma_handle, ovl->fb_size); 1627bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU} 1628bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU 1629c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic struct fb_ops sh_mobile_lcdc_overlay_ops = { 1630c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .owner = THIS_MODULE, 1631c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_read = fb_sys_read, 1632c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_write = fb_sys_write, 1633c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_fillrect = sys_fillrect, 1634c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_copyarea = sys_copyarea, 1635c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_imageblit = sys_imageblit, 1636c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_blank = sh_mobile_lcdc_overlay_blank, 1637c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_pan_display = sh_mobile_lcdc_overlay_pan, 1638c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_ioctl = sh_mobile_lcdc_overlay_ioctl, 1639c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_check_var = sh_mobile_lcdc_overlay_check_var, 1640c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_set_par = sh_mobile_lcdc_overlay_set_par, 1641bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU .fb_mmap = sh_mobile_lcdc_overlay_mmap, 1642c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 1643c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1644c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic void 1645c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl) 1646c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1647c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = ovl->info; 1648c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1649c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL || info->dev == NULL) 1650c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return; 1651c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1652c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unregister_framebuffer(ovl->info); 1653c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1654c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 165548c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int 1656c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl) 1657c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1658c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc; 1659c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = ovl->info; 1660c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int i; 1661c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int ret; 1662c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1663c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL) 1664c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1665c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1666c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = register_framebuffer(info); 1667c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 1668c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 1669c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1670c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n", 1671c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dev_name(lcdc->dev), ovl->index, info->var.xres, 1672c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->var.yres, info->var.bits_per_pixel); 1673c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1674c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) { 1675c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]); 1676c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 1677c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 1678c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1679c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1680c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1681c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1682c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1683c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic void 1684c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl) 1685c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1686c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = ovl->info; 1687c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1688c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL || info->device == NULL) 1689c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return; 1690c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1691c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart framebuffer_release(info); 1692c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1693c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 169448c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int 1695c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) 1696c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1697c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc; 1698c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_var_screeninfo *var; 1699c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info; 1700c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1701c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Allocate and initialize the frame buffer device. */ 1702c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info = framebuffer_alloc(0, priv->dev); 1703c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL) { 1704c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dev_err(priv->dev, "unable to allocate fb_info\n"); 1705c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -ENOMEM; 1706c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1707c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1708c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->info = info; 1709c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1710c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->flags = FBINFO_FLAG_DEFAULT; 1711c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fbops = &sh_mobile_lcdc_overlay_ops; 1712c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->device = priv->dev; 1713c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->screen_base = ovl->fb_mem; 1714c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->par = ovl; 1715c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1716c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Initialize fixed screen information. Restrict pan to 2 lines steps 1717c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * for NV12 and NV21. 1718c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1719c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix = sh_mobile_lcdc_overlay_fix; 1720c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart snprintf(info->fix.id, sizeof(info->fix.id), 1721c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart "SH Mobile LCDC Overlay %u", ovl->index); 1722c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.smem_start = ovl->dma_handle; 1723c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.smem_len = ovl->fb_size; 1724c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.line_length = ovl->pitch; 1725c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1726c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->format->yuv) 1727c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 1728c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 1729c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 1730c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 173115dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart switch (ovl->format->fourcc) { 173215dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart case V4L2_PIX_FMT_NV12: 173315dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart case V4L2_PIX_FMT_NV21: 1734ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart info->fix.ypanstep = 2; 1735ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart case V4L2_PIX_FMT_NV16: 1736ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart case V4L2_PIX_FMT_NV61: 173715dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart info->fix.xpanstep = 2; 173815dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart } 1739c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1740c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Initialize variable screen information. */ 1741c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var = &info->var; 1742c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart memset(var, 0, sizeof(*var)); 1743c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->xres = ovl->xres; 1744c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->yres = ovl->yres; 1745c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->xres_virtual = ovl->xres_virtual; 1746c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->yres_virtual = ovl->yres_virtual; 1747c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->activate = FB_ACTIVATE_NOW; 1748c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1749c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Use the legacy API by default for RGB formats, and the FOURCC API 1750c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * for YUV formats. 1751c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1752c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!ovl->format->yuv) 1753c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = ovl->format->bpp; 1754c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 1755c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->grayscale = ovl->format->fourcc; 1756c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1757c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return sh_mobile_lcdc_overlay_check_var(var, info); 1758c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1759c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1760f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 1761c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * Frame buffer operations - main frame buffer 1762f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 1763cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1764cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic int sh_mobile_lcdc_setcolreg(u_int regno, 1765cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm u_int red, u_int green, u_int blue, 1766cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm u_int transp, struct fb_info *info) 1767cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 1768cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm u32 *palette = info->pseudo_palette; 1769cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1770cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (regno >= PALETTE_NR) 1771cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return -EINVAL; 1772cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1773cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* only FB_VISUAL_TRUECOLOR supported */ 1774cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1775cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm red >>= 16 - info->var.red.length; 1776cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm green >>= 16 - info->var.green.length; 1777cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm blue >>= 16 - info->var.blue.length; 1778cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm transp >>= 16 - info->var.transp.length; 1779cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1780cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm palette[regno] = (red << info->var.red.offset) | 1781cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm (green << info->var.green.offset) | 1782cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm (blue << info->var.blue.offset) | 1783cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm (transp << info->var.transp.offset); 1784cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1785cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return 0; 1786cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 1787cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 17883281e54c80195b90ed12a5b6cddef4ab42e656e1Laurent Pinchartstatic const struct fb_fix_screeninfo sh_mobile_lcdc_fix = { 1789cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .id = "SH Mobile LCDC", 1790cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .type = FB_TYPE_PACKED_PIXELS, 1791cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .visual = FB_VISUAL_TRUECOLOR, 1792cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .accel = FB_ACCEL_NONE, 179315dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart .xpanstep = 1, 17949dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy .ypanstep = 1, 17959dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy .ywrapstep = 0, 1796edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart .capabilities = FB_CAP_FOURCC, 1797cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 1798cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 17998564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_fillrect(struct fb_info *info, 18008564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm const struct fb_fillrect *rect) 18018564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 18028564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sys_fillrect(info, rect); 18038564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_deferred_io_touch(info); 18048564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 18058564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 18068564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_copyarea(struct fb_info *info, 18078564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm const struct fb_copyarea *area) 18088564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 18098564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sys_copyarea(info, area); 18108564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_deferred_io_touch(info); 18118564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 18128564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 18138564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_imageblit(struct fb_info *info, 18148564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm const struct fb_image *image) 18158564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 18168564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sys_imageblit(info, image); 18178564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_deferred_io_touch(info); 18188564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 18198564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 1820d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var, 1821d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart struct fb_info *info) 18229dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy{ 18239dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy struct sh_mobile_lcdc_chan *ch = info->par; 182492e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy struct sh_mobile_lcdc_priv *priv = ch->lcdc; 182592e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy unsigned long ldrcntr; 1826a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned long base_addr_y, base_addr_c; 1827a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned long y_offset; 182853b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia unsigned long c_offset; 182992e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy 1830a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart if (!ch->format->yuv) { 1831a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart y_offset = (var->yoffset * ch->xres_virtual + var->xoffset) 1832a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart * ch->format->bpp / 8; 1833a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart c_offset = 0; 1834a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart } else { 1835a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned int xsub = ch->format->bpp < 24 ? 2 : 1; 1836a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned int ysub = ch->format->bpp < 16 ? 2 : 1; 18379dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 1838a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart y_offset = var->yoffset * ch->xres_virtual + var->xoffset; 1839a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart c_offset = var->yoffset / ysub * ch->xres_virtual * 2 / xsub 1840a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + var->xoffset * 2 / xsub; 1841a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart } 18429dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 1843a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart /* If the Y offset hasn't changed, the C offset hasn't either. There's 1844a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart * nothing to do in that case. 1845a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart */ 1846a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart if (y_offset == ch->pan_y_offset) 1847a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart return 0; 18489dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 184992e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy /* Set the source address for the next refresh */ 1850a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart base_addr_y = ch->dma_handle + y_offset; 1851a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual 1852a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + c_offset; 185353b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia 18546e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart if (ch->cache) 18556e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_update(priv->meram_dev, ch->cache, 18566e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart base_addr_y, base_addr_c, 18576e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart &base_addr_y, &base_addr_c); 18587caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 185949d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart ch->base_addr_y = base_addr_y; 186049d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart ch->base_addr_c = base_addr_c; 1861a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ch->pan_y_offset = y_offset; 18627caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 186349d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); 186458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ch->format->yuv) 186549d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); 186653b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia 1867a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ldrcntr = lcdc_read(priv, _LDRCNTR); 186892e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy if (lcdc_chan_is_sublcd(ch)) 186992e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); 187092e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy else 187192e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS); 187292e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy 187392e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy 187492e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy sh_mobile_lcdc_deferred_io_touch(info); 18759dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 18769dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy return 0; 18779dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy} 18789dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 1879d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_ioctl(struct fb_info *info, unsigned int cmd, 1880d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart unsigned long arg) 188140331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy{ 1882d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart struct sh_mobile_lcdc_chan *ch = info->par; 188340331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy int retval; 188440331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 188540331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy switch (cmd) { 188640331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy case FBIO_WAITFORVSYNC: 1887d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart retval = sh_mobile_lcdc_wait_for_vsync(ch); 188840331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy break; 188940331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 189040331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy default: 189140331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy retval = -ENOIOCTLCMD; 189240331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy break; 189340331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy } 189440331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy return retval; 189540331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy} 189640331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 1897dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetskistatic void sh_mobile_fb_reconfig(struct fb_info *info) 1898dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1899dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 19002d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart struct fb_var_screeninfo var; 19012d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart struct fb_videomode mode; 1902dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct fb_event event; 1903dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski int evnt = FB_EVENT_MODE_CHANGE_ALL; 1904dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1905dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par)) 1906dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* More framebuffer users are active */ 1907dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return; 1908dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 19092d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart fb_var_to_videomode(&mode, &info->var); 1910dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 19112d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart if (fb_mode_is_equal(&ch->display.mode, &mode)) 1912dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return; 1913dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1914dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* Display has been re-plugged, framebuffer is free now, reconfigure */ 19152d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var = info->var; 19162d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart fb_videomode_to_var(&var, &ch->display.mode); 19172d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var.width = ch->display.width; 19182d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var.height = ch->display.height; 19192d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var.activate = FB_ACTIVATE_NOW; 19202d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart 19212d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart if (fb_set_var(info, &var) < 0) 1922dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* Couldn't reconfigure, hopefully, can continue as before */ 1923dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return; 1924dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1925dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* 1926dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * fb_set_var() calls the notifier change internally, only if 1927dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a 1928dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * user event, we have to call the chain ourselves. 1929dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski */ 1930dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski event.info = info; 19312d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart event.data = &ch->display.mode; 1932dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski fb_notifier_call_chain(evnt, &event); 1933dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 1934dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1935dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski/* 1936dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * Locking: both .fb_release() and .fb_open() are called with info->lock held if 1937dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * user == 1, or with console sem held, if user == 0. 1938dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski */ 1939d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_release(struct fb_info *info, int user) 1940dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1941dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 1942dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1943dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_lock(&ch->open_lock); 1944dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count); 1945dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1946dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski ch->use_count--; 1947dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1948dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* Nothing to reconfigure, when called from fbcon */ 1949dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski if (user) { 1950ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 1951dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski sh_mobile_fb_reconfig(info); 1952ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 1953dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski } 1954dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1955dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_unlock(&ch->open_lock); 1956dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1957dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return 0; 1958dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 1959dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1960d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_open(struct fb_info *info, int user) 1961dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1962dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 1963dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1964dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_lock(&ch->open_lock); 1965dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski ch->use_count++; 1966dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1967dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count); 1968dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_unlock(&ch->open_lock); 1969dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1970dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return 0; 1971dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 1972dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1973d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, 1974d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart struct fb_info *info) 1975dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1976dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 1977417d48274e755e537bae60461558c1f63a4e14deMagnus Damm struct sh_mobile_lcdc_priv *p = ch->lcdc; 19780386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int best_dist = (unsigned int)-1; 19790386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int best_xres = 0; 19800386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int best_yres = 0; 19810386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int i; 1982c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int ret; 19830386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19840386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart /* If board code provides us with a list of available modes, make sure 19850386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * we use one of them. Find the mode closest to the requested one. The 19860386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * distance between two modes is defined as the size of the 19870386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * non-overlapping parts of the two rectangles. 19880386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart */ 1989b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart for (i = 0; i < ch->cfg->num_modes; ++i) { 1990b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct fb_videomode *mode = &ch->cfg->lcd_modes[i]; 19910386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int dist; 19920386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19930386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart /* We can only round up. */ 19940386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart if (var->xres > mode->xres || var->yres > mode->yres) 19950386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart continue; 19960386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19970386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart dist = var->xres * var->yres + mode->xres * mode->yres 19980386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart - 2 * min(var->xres, mode->xres) 19990386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * min(var->yres, mode->yres); 20000386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 20010386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart if (dist < best_dist) { 20020386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart best_xres = mode->xres; 20030386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart best_yres = mode->yres; 20040386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart best_dist = dist; 20050386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart } 2006dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski } 2007417d48274e755e537bae60461558c1f63a4e14deMagnus Damm 20080386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart /* If no available mode can be used, return an error. */ 2009b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart if (ch->cfg->num_modes != 0) { 20100386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart if (best_dist == (unsigned int)-1) 20110386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart return -EINVAL; 20120386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 20130386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart var->xres = best_xres; 20140386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart var->yres = best_yres; 20150386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart } 20160386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 2017c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = __sh_mobile_lcdc_check_var(var, info); 2018c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 2019c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 20200386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 2021edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart /* only accept the forced_fourcc for dual channel configurations */ 2022edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart if (p->forced_fourcc && 2023edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart p->forced_fourcc != sh_mobile_format_fourcc(var)) 2024417d48274e755e537bae60461558c1f63a4e14deMagnus Damm return -EINVAL; 2025417d48274e755e537bae60461558c1f63a4e14deMagnus Damm 2026dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return 0; 2027dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 202840331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 2029d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_set_par(struct fb_info *info) 2030ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart{ 2031ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart struct sh_mobile_lcdc_chan *ch = info->par; 2032ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart int ret; 2033ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart 2034ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart sh_mobile_lcdc_stop(ch->lcdc); 203591fba48d59666718e3d3e86964755b80d39cdbddLaurent Pinchart 2036fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var)); 203758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->colorspace = info->var.colorspace; 203858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 203958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres = info->var.xres; 204058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres_virtual = info->var.xres_virtual; 204158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres = info->var.yres; 204258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres_virtual = info->var.yres_virtual; 204358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 204458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ch->format->yuv) 204516ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ch->pitch = info->var.xres_virtual; 204658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart else 204716ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ch->pitch = info->var.xres_virtual * ch->format->bpp / 8; 2048fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart 2049ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart ret = sh_mobile_lcdc_start(ch->lcdc); 205058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ret < 0) 2051ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart dev_err(info->dev, "%s: unable to restart LCDC\n", __func__); 205258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 205358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.line_length = ch->pitch; 2054ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart 2055edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart if (sh_mobile_format_is_fourcc(&info->var)) { 2056edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.type = FB_TYPE_FOURCC; 2057edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 2058edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart } else { 2059edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.type = FB_TYPE_PACKED_PIXELS; 2060edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 2061edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart } 2062edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart 2063ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart return ret; 2064ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart} 2065ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart 20668857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot/* 20678857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * Screen blanking. Behavior is as follows: 20688857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_UNBLANK: screen unblanked, clocks enabled 20698857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_NORMAL: screen blanked, clocks enabled 20708857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_VSYNC, 20718857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_HSYNC, 20728857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_POWEROFF: screen blanked, clocks disabled 20738857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot */ 20748857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbotstatic int sh_mobile_lcdc_blank(int blank, struct fb_info *info) 20758857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot{ 20768857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot struct sh_mobile_lcdc_chan *ch = info->par; 20778857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot struct sh_mobile_lcdc_priv *p = ch->lcdc; 20788857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot 20798857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* blank the screen? */ 20808857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) { 20818857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot struct fb_fillrect rect = { 208258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart .width = ch->xres, 208358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart .height = ch->yres, 20848857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot }; 20858857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot sh_mobile_lcdc_fillrect(info, &rect); 20868857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 20878857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* turn clocks on? */ 20888857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) { 20898857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot sh_mobile_lcdc_clk_on(p); 20908857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 20918857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* turn clocks off? */ 20928857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) { 20938857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* make sure the screen is updated with the black fill before 20948857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * switching the clocks off. one vsync is not enough since 20958857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * blanking may occur in the middle of a refresh. deferred io 20968857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * mode will reenable the clocks and update the screen in time, 20978857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * so it does not need this. */ 20988857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (!info->fbdefio) { 2099d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart sh_mobile_lcdc_wait_for_vsync(ch); 2100d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart sh_mobile_lcdc_wait_for_vsync(ch); 21018857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 21028857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot sh_mobile_lcdc_clk_off(p); 21038857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 21048857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot 21058857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot ch->blank_status = blank; 21068857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot return 0; 21078857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot} 21088857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot 2109bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKUstatic int 2110bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKUsh_mobile_lcdc_mmap(struct fb_info *info, struct vm_area_struct *vma) 2111bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU{ 2112bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU struct sh_mobile_lcdc_chan *ch = info->par; 2113bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU 2114bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem, 2115bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU ch->dma_handle, ch->fb_size); 2116bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU} 2117bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU 2118cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic struct fb_ops sh_mobile_lcdc_ops = { 21199dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy .owner = THIS_MODULE, 2120cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .fb_setcolreg = sh_mobile_lcdc_setcolreg, 21212540c111ead82cad605ec2b14a1905ad914cc124Magnus Damm .fb_read = fb_sys_read, 21222540c111ead82cad605ec2b14a1905ad914cc124Magnus Damm .fb_write = fb_sys_write, 21238564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm .fb_fillrect = sh_mobile_lcdc_fillrect, 21248564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm .fb_copyarea = sh_mobile_lcdc_copyarea, 21258564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm .fb_imageblit = sh_mobile_lcdc_imageblit, 21268857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot .fb_blank = sh_mobile_lcdc_blank, 2127d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_pan_display = sh_mobile_lcdc_pan, 2128d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_ioctl = sh_mobile_lcdc_ioctl, 2129d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_open = sh_mobile_lcdc_open, 2130d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_release = sh_mobile_lcdc_release, 2131d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_check_var = sh_mobile_lcdc_check_var, 2132d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_set_par = sh_mobile_lcdc_set_par, 2133bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU .fb_mmap = sh_mobile_lcdc_mmap, 2134cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 2135cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2136a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartstatic void 2137a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_unregister(struct sh_mobile_lcdc_chan *ch) 2138a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2139a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->info && ch->info->dev) 2140a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unregister_framebuffer(ch->info); 2141a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2142a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 214348c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int 2144a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch) 2145a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2146a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_info *info = ch->info; 2147a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart int ret; 2148a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2149a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (info->fbdefio) { 2150a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->sglist = vmalloc(sizeof(struct scatterlist) * 2151a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->fb_size >> PAGE_SHIFT); 2152a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (!ch->sglist) { 2153a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_err(ch->lcdc->dev, "cannot allocate sglist\n"); 2154a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return -ENOMEM; 2155a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2156a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2157a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2158a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->bl_dev = ch->bl; 2159a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2160a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ret = register_framebuffer(info); 2161a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ret < 0) 2162a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2163a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2164a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_info(ch->lcdc->dev, "registered %s/%s as %dx%d %dbpp.\n", 2165b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart dev_name(ch->lcdc->dev), (ch->cfg->chan == LCDC_CHAN_MAINLCD) ? 2166a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart "mainlcd" : "sublcd", info->var.xres, info->var.yres, 2167a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->var.bits_per_pixel); 2168a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2169a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* deferred io mode: disable clock to save power */ 2170a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED) 2171a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart sh_mobile_lcdc_clk_off(ch->lcdc); 2172a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2173a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2174a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2175a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2176a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartstatic void 2177a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch) 2178a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2179a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_info *info = ch->info; 2180a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2181a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (!info || !info->device) 2182a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return; 2183a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2184a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->sglist) 2185a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart vfree(ch->sglist); 2186a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2187a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart fb_dealloc_cmap(&info->cmap); 2188a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart framebuffer_release(info); 2189a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2190a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 219148c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int 2192a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, 2193352d6138779e22c5340803d5a32fc332ad2e5e1dLaurent Pinchart const struct fb_videomode *modes, 2194a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unsigned int num_modes) 2195a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2196a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct sh_mobile_lcdc_priv *priv = ch->lcdc; 2197a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_var_screeninfo *var; 2198a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_info *info; 2199a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart int ret; 2200a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2201a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Allocate and initialize the frame buffer device. Create the modes 2202a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart * list and allocate the color map. 2203a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2204a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info = framebuffer_alloc(0, priv->dev); 2205a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (info == NULL) { 2206a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_err(priv->dev, "unable to allocate fb_info\n"); 2207a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return -ENOMEM; 2208a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2209a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2210a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->info = info; 2211a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2212a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->flags = FBINFO_FLAG_DEFAULT; 2213a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fbops = &sh_mobile_lcdc_ops; 2214a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->device = priv->dev; 2215a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->screen_base = ch->fb_mem; 2216a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->pseudo_palette = &ch->pseudo_palette; 2217a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->par = ch; 2218a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2219352d6138779e22c5340803d5a32fc332ad2e5e1dLaurent Pinchart fb_videomode_to_modelist(modes, num_modes, &info->modelist); 2220a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2221a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); 2222a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ret < 0) { 2223a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_err(priv->dev, "unable to allocate cmap\n"); 2224a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2225a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2226a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2227a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Initialize fixed screen information. Restrict pan to 2 lines steps 2228a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart * for NV12 and NV21. 2229a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2230a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fix = sh_mobile_lcdc_fix; 2231a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fix.smem_start = ch->dma_handle; 2232a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fix.smem_len = ch->fb_size; 223358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.line_length = ch->pitch; 223458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 223558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ch->format->yuv) 223658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 223758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart else 223858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 223958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 224015dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart switch (ch->format->fourcc) { 224115dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart case V4L2_PIX_FMT_NV12: 224215dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart case V4L2_PIX_FMT_NV21: 2243ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart info->fix.ypanstep = 2; 2244ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart case V4L2_PIX_FMT_NV16: 2245ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart case V4L2_PIX_FMT_NV61: 224615dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart info->fix.xpanstep = 2; 224715dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart } 2248a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2249a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Initialize variable screen information using the first mode as 2250bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart * default. 2251a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2252a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var = &info->var; 2253352d6138779e22c5340803d5a32fc332ad2e5e1dLaurent Pinchart fb_videomode_to_var(var, modes); 2254856e8dfe6efed7cf35bc6bf827f030a164bee083Laurent Pinchart var->width = ch->display.width; 2255856e8dfe6efed7cf35bc6bf827f030a164bee083Laurent Pinchart var->height = ch->display.height; 2256bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart var->xres_virtual = ch->xres_virtual; 2257bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart var->yres_virtual = ch->yres_virtual; 2258a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var->activate = FB_ACTIVATE_NOW; 2259a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2260a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Use the legacy API by default for RGB formats, and the FOURCC API 2261a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart * for YUV formats. 2262a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2263a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (!ch->format->yuv) 2264a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var->bits_per_pixel = ch->format->bpp; 2265a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart else 2266a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var->grayscale = ch->format->fourcc; 2267a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2268d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart ret = sh_mobile_lcdc_check_var(var, info); 2269a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ret) 2270a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2271a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2272a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return 0; 2273a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2274a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2275f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2276f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Backlight 2277f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2278f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 22793b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) 22803b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 22813b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); 22823b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot int brightness = bdev->props.brightness; 22833b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22843b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot if (bdev->props.power != FB_BLANK_UNBLANK || 22853b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) 22863b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot brightness = 0; 22873b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2288656d4f332c02b14e62fe3f4247a1dcdc33961de6Laurent Pinchart ch->bl_brightness = brightness; 2289b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart return ch->cfg->bl_info.set_brightness(brightness); 22903b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 22913b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22923b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev) 22933b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 22943b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); 22953b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2296656d4f332c02b14e62fe3f4247a1dcdc33961de6Laurent Pinchart return ch->bl_brightness; 22973b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 22983b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22993b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic int sh_mobile_lcdc_check_fb(struct backlight_device *bdev, 23003b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct fb_info *info) 23013b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 23023b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot return (info->bl_dev == bdev); 23033b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 23043b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 23053b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic struct backlight_ops sh_mobile_lcdc_bl_ops = { 23063b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .options = BL_CORE_SUSPENDRESUME, 23073b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .update_status = sh_mobile_lcdc_update_bl, 23083b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .get_brightness = sh_mobile_lcdc_get_brightness, 23093b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .check_fb = sh_mobile_lcdc_check_fb, 23103b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot}; 23113b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 23123b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent, 23133b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct sh_mobile_lcdc_chan *ch) 23143b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 23153b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct backlight_device *bl; 23163b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2317b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart bl = backlight_device_register(ch->cfg->bl_info.name, parent, ch, 23183b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot &sh_mobile_lcdc_bl_ops, NULL); 2319beee1f20a185c7e79fd33bb83e04fe44ecd75af3Dan Carpenter if (IS_ERR(bl)) { 2320beee1f20a185c7e79fd33bb83e04fe44ecd75af3Dan Carpenter dev_err(parent, "unable to register backlight device: %ld\n", 2321beee1f20a185c7e79fd33bb83e04fe44ecd75af3Dan Carpenter PTR_ERR(bl)); 23223b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot return NULL; 23233b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot } 23243b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2325b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart bl->props.max_brightness = ch->cfg->bl_info.max_brightness; 23263b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot bl->props.brightness = bl->props.max_brightness; 23273b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_update_status(bl); 23283b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 23293b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot return bl; 23303b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 23313b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 23323b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev) 23333b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 23343b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_device_unregister(bdev); 23353b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 23363b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2337f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2338f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Power management 2339f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2340f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 23412feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Dammstatic int sh_mobile_lcdc_suspend(struct device *dev) 23422feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm{ 23432feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23442feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23452feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm sh_mobile_lcdc_stop(platform_get_drvdata(pdev)); 23462feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm return 0; 23472feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm} 23482feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23492feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Dammstatic int sh_mobile_lcdc_resume(struct device *dev) 23502feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm{ 23512feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23522feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23532feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm return sh_mobile_lcdc_start(platform_get_drvdata(pdev)); 23542feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm} 23552feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23560246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Dammstatic int sh_mobile_lcdc_runtime_suspend(struct device *dev) 23570246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm{ 23580246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23592427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 23600246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23610246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm /* turn off LCDC hardware */ 23622427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart lcdc_write(priv, _LDCNT1R, 0); 23632427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart 23640246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm return 0; 23650246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm} 23660246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23670246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Dammstatic int sh_mobile_lcdc_runtime_resume(struct device *dev) 23680246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm{ 23690246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23702427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 23710246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23722427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart __sh_mobile_lcdc_start(priv); 23730246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23740246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm return 0; 23750246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm} 23760246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 2377471452104b8520337ae2fb48c4e61cd4896e025dAlexey Dobriyanstatic const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { 23782feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm .suspend = sh_mobile_lcdc_suspend, 23792feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm .resume = sh_mobile_lcdc_resume, 23800246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm .runtime_suspend = sh_mobile_lcdc_runtime_suspend, 23810246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm .runtime_resume = sh_mobile_lcdc_runtime_resume, 23822feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm}; 23832feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 2384f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2385f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Framebuffer notifier 2386f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2387f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 23886de9edd5bde0cdfea12e9948690e53ec669c3018Guennadi Liakhovetski/* locking: called with info->lock held */ 23896011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetskistatic int sh_mobile_lcdc_notify(struct notifier_block *nb, 23906011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski unsigned long action, void *data) 23916011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski{ 23926011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski struct fb_event *event = data; 23936011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski struct fb_info *info = event->info; 23946011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 23956011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 23966011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski if (&ch->lcdc->notifier != nb) 2397baf163749952ca5e33dd2d6a74da023e385c3a00Guennadi Liakhovetski return NOTIFY_DONE; 23986011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 23996011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", 24006011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski __func__, action, event->data); 24016011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 24026011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski switch(action) { 24036011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski case FB_EVENT_SUSPEND: 240437c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_off(ch); 2405afe417c0355154c8b2547619771d6053b3c0aad7Guennadi Liakhovetski sh_mobile_lcdc_stop(ch->lcdc); 24066011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski break; 24076011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski case FB_EVENT_RESUME: 2408dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_lock(&ch->open_lock); 2409dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski sh_mobile_fb_reconfig(info); 2410dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_unlock(&ch->open_lock); 24116011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 241237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_on(ch); 2413ebe5e12d00f4785092a9650845ad3451bbf4b311Guennadi Liakhovetski sh_mobile_lcdc_start(ch->lcdc); 24146011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski } 24156011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 2416baf163749952ca5e33dd2d6a74da023e385c3a00Guennadi Liakhovetski return NOTIFY_OK; 24176011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski} 24186011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 2419f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2420f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Probe/remove and driver init/exit 2421f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2422f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 242348c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic const struct fb_videomode default_720p = { 2424f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .name = "HDMI 720p", 2425f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .xres = 1280, 2426f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .yres = 720, 2427f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2428f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .left_margin = 220, 2429f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .right_margin = 110, 2430f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .hsync_len = 40, 2431f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2432f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .upper_margin = 20, 2433f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .lower_margin = 5, 2434f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .vsync_len = 5, 2435f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2436f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .pixclock = 13468, 2437f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .refresh = 60, 2438f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, 2439f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart}; 2440f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2441b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchartstatic int sh_mobile_lcdc_remove(struct platform_device *pdev) 2442b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart{ 2443b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 2444c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int i; 2445b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2446b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart fb_unregister_client(&priv->notifier); 2447b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2448c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) 2449c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]); 2450b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->ch); i++) 2451a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]); 2452b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2453b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart sh_mobile_lcdc_stop(priv); 2454b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2455c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) { 2456c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; 2457c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2458c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_fb_cleanup(ovl); 2459c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2460c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->fb_mem) 2461c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dma_free_coherent(&pdev->dev, ovl->fb_size, 2462c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->fb_mem, ovl->dma_handle); 2463c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2464c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2465b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { 24669a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; 2467b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2468e34d0bbb062cc78802d0f0686c939ea1569889a6Laurent Pinchart if (ch->tx_dev) { 2469e34d0bbb062cc78802d0f0686c939ea1569889a6Laurent Pinchart ch->tx_dev->lcdc = NULL; 2470b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart module_put(ch->cfg->tx_dev->dev.driver->owner); 2471e34d0bbb062cc78802d0f0686c939ea1569889a6Laurent Pinchart } 24729a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart 2473a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart sh_mobile_lcdc_channel_fb_cleanup(ch); 2474b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2475a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->fb_mem) 2476a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dma_free_coherent(&pdev->dev, ch->fb_size, 2477a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->fb_mem, ch->dma_handle); 2478b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart } 2479b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2480b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { 24810c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; 24820c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart 24830c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart if (ch->bl) 24840c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart sh_mobile_lcdc_bl_remove(ch->bl); 24850c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart mutex_destroy(&ch->open_lock); 2486b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart } 2487b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 24884774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart if (priv->dot_clk) { 24894774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart pm_runtime_disable(&pdev->dev); 2490b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart clk_put(priv->dot_clk); 24914774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart } 2492b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2493b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart if (priv->base) 2494b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart iounmap(priv->base); 2495b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2496b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart if (priv->irq) 2497b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart free_irq(priv->irq, priv); 2498b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart kfree(priv); 2499b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart return 0; 2500b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart} 2501cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 250248c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) 2503f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 2504b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart int interface_type = ch->cfg->interface_type; 2505f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2506f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart switch (interface_type) { 2507f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB8: 2508f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB9: 2509f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB12A: 2510f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB12B: 2511f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB16: 2512f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB18: 2513f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB24: 2514f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8A: 2515f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8B: 2516f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8C: 2517f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8D: 2518f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS9: 2519f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS12: 2520f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS16A: 2521f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS16B: 2522f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS16C: 2523f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS18: 2524f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS24: 2525f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart break; 2526f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart default: 2527f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return -EINVAL; 2528f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 2529f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2530f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart /* SUBLCD only supports SYS interface */ 2531f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (lcdc_chan_is_sublcd(ch)) { 2532f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (!(interface_type & LDMT1R_IFM)) 2533f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return -EINVAL; 2534f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2535f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart interface_type &= ~LDMT1R_IFM; 2536f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 2537f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2538f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart ch->ldmt1r_value = interface_type; 2539f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return 0; 2540f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 2541f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 254248c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int 25430707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchartsh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl) 2544c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 2545c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const struct sh_mobile_lcdc_format_info *format; 25460707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart struct device *dev = ovl->channel->lcdc->dev; 2547c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int ret; 2548c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2549c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->cfg->fourcc == 0) 2550c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 2551c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2552c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Validate the format. */ 2553c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = sh_mobile_format_info(ovl->cfg->fourcc); 2554c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (format == NULL) { 25550707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc); 2556c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 2557c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2558c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2559c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->enabled = false; 2560c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->mode = LCDC_OVERLAY_BLEND; 2561c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->alpha = 255; 2562c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->rop3 = 0; 2563c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_x = 0; 2564c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_y = 0; 2565c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2566c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* The default Y virtual resolution is twice the panel size to allow for 2567c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * double-buffering. 2568c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 2569c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->format = format; 2570c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres = ovl->cfg->max_xres; 2571c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres_virtual = ovl->xres; 2572c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres = ovl->cfg->max_yres; 2573c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres_virtual = ovl->yres * 2; 2574c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2575c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!format->yuv) 257616ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ovl->pitch = ovl->xres_virtual * format->bpp / 8; 2577c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 257816ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ovl->pitch = ovl->xres_virtual; 2579c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2580c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Allocate frame buffer memory. */ 2581c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres 2582c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * format->bpp / 8 * 2; 25830707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle, 25840707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart GFP_KERNEL); 2585c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!ovl->fb_mem) { 25860707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_err(dev, "unable to allocate buffer\n"); 2587c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -ENOMEM; 2588c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2589c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2590c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = sh_mobile_lcdc_overlay_fb_init(ovl); 2591c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 2592c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 2593c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2594c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 2595c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 2596c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 259748c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int 25980707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchartsh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch) 2599cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 2600105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart const struct sh_mobile_lcdc_format_info *format; 2601b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg; 26020707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart struct device *dev = ch->lcdc->dev; 26033ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart const struct fb_videomode *max_mode; 26043ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart const struct fb_videomode *mode; 2605a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unsigned int num_modes; 26063ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart unsigned int max_size; 2607a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unsigned int i; 26083ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 2609a67472ad1ae040f073e45048cbc5a01195f2e3f5Laurent Pinchart mutex_init(&ch->open_lock); 2610ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart ch->notify = sh_mobile_lcdc_display_notify; 2611a67472ad1ae040f073e45048cbc5a01195f2e3f5Laurent Pinchart 2612105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart /* Validate the format. */ 2613105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart format = sh_mobile_format_info(cfg->fourcc); 2614105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart if (format == NULL) { 26150707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc); 2616105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart return -EINVAL; 2617105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart } 2618105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 26193ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart /* Iterate through the modes to validate them and find the highest 26203ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart * resolution. 26213ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart */ 26223ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_mode = NULL; 26233ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_size = 0; 26243ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 262593ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart for (i = 0, mode = cfg->lcd_modes; i < cfg->num_modes; i++, mode++) { 26263ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart unsigned int size = mode->yres * mode->xres; 26273ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 2628edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart /* NV12/NV21 buffers must have even number of lines */ 2629edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart if ((cfg->fourcc == V4L2_PIX_FMT_NV12 || 2630edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) { 26310707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_err(dev, "yres must be multiple of 2 for " 26320a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart "YCbCr420 mode.\n"); 26333ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart return -EINVAL; 26343ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26353ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 26363ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (size > max_size) { 26373ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_mode = mode; 26383ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_size = size; 26393ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26403ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26413ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 26423ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (!max_size) 26433ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_size = MAX_XRES * MAX_YRES; 26443ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart else 26450707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_dbg(dev, "Found largest videomode %ux%u\n", 26463ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_mode->xres, max_mode->yres); 26473ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 264893ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart if (cfg->lcd_modes == NULL) { 26493ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart mode = &default_720p; 265093ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart num_modes = 1; 26513ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } else { 265293ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart mode = cfg->lcd_modes; 265393ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart num_modes = cfg->num_modes; 26543ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26553ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 2656bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart /* Use the first mode as default. The default Y virtual resolution is 2657bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart * twice the panel size to allow for double-buffering. 2658bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart */ 265958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->format = format; 266058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres = mode->xres; 266158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres_virtual = mode->xres; 266258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres = mode->yres; 266358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres_virtual = mode->yres * 2; 266458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 266558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (!format->yuv) { 266658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->colorspace = V4L2_COLORSPACE_SRGB; 266716ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ch->pitch = ch->xres_virtual * format->bpp / 8; 266858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart } else { 266958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->colorspace = V4L2_COLORSPACE_REC709; 267016ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ch->pitch = ch->xres_virtual; 267158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart } 267258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 2673a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->display.width = cfg->panel_cfg.width; 2674a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->display.height = cfg->panel_cfg.height; 2675a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->display.mode = *mode; 2676a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2677a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Allocate frame buffer memory. */ 2678a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->fb_size = max_size * format->bpp / 8 * 2; 26790707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle, 2680a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart GFP_KERNEL); 2681a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->fb_mem == NULL) { 26820707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_err(dev, "unable to allocate buffer\n"); 2683a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return -ENOMEM; 2684a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 26853ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 268613f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart /* Initialize the transmitter device if present. */ 268713f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart if (cfg->tx_dev) { 268813f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart if (!cfg->tx_dev->dev.driver || 268913f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart !try_module_get(cfg->tx_dev->dev.driver->owner)) { 26900707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_warn(dev, "unable to get transmitter device\n"); 269113f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart return -EINVAL; 269213f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart } 269313f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart ch->tx_dev = platform_get_drvdata(cfg->tx_dev); 269413f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart ch->tx_dev->lcdc = ch; 269513f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart ch->tx_dev->def_mode = *mode; 269613f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart } 269713f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart 2698a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return sh_mobile_lcdc_channel_fb_init(ch, mode, num_modes); 26993ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart} 27003ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 270148c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int sh_mobile_lcdc_probe(struct platform_device *pdev) 27023ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart{ 270301ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; 27043ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart struct sh_mobile_lcdc_priv *priv; 2705cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct resource *res; 27063ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart int num_channels; 2707cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int error; 27083ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart int i; 2709cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 271001ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski if (!pdata) { 2711cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "no platform data defined\n"); 27128bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski return -EINVAL; 2713cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2714cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2715cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 27168564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm i = platform_get_irq(pdev, 0); 27178564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm if (!res || i < 0) { 27188564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm dev_err(&pdev->dev, "cannot get platform resources\n"); 27198bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski return -ENOENT; 2720cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2721cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2722cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm priv = kzalloc(sizeof(*priv), GFP_KERNEL); 2723cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!priv) { 2724cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "cannot allocate device data\n"); 27258bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski return -ENOMEM; 2726cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2727cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27284774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart priv->dev = &pdev->dev; 27294774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart priv->meram_dev = pdata->meram_dev; 27308bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski platform_set_drvdata(pdev, priv); 27318bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski 2732f8798ccbefc0e4ef7438c080b7ba0410738c8cfaYong Zhang error = request_irq(i, sh_mobile_lcdc_irq, 0, 27337ad33e74857f16f1202cbc5746faf52e88e8b376Kay Sievers dev_name(&pdev->dev), priv); 27348564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm if (error) { 27358564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm dev_err(&pdev->dev, "unable to request irq\n"); 27368564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm goto err1; 27378564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm } 27388564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 27398564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm priv->irq = i; 27405ef6b505d9df45558402bdb823a078840a6a26c4Guennadi Liakhovetski atomic_set(&priv->hw_usecnt, -1); 2741cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27423ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) { 27433ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels; 2744cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 274501ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski ch->lcdc = priv; 2746b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart ch->cfg = &pdata->ch[i]; 2747cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 274801ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski error = sh_mobile_lcdc_check_interface(ch); 2749cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) { 2750cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "unsupported interface type\n"); 2751cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2752cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 275301ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski init_waitqueue_head(&ch->frame_end_wait); 275401ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski init_completion(&ch->vsync_completion); 2755cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27563b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot /* probe the backlight is there is one defined */ 2757b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart if (ch->cfg->bl_info.max_brightness) 27583b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch); 27593b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2760cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm switch (pdata->ch[i].chan) { 2761cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm case LCDC_CHAN_MAINLCD: 2762ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart ch->enabled = LDCNT2R_ME; 276301ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski ch->reg_offs = lcdc_offs_mainlcd; 27643ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart num_channels++; 2765cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 2766cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm case LCDC_CHAN_SUBLCD: 2767ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart ch->enabled = LDCNT2R_SE; 276801ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski ch->reg_offs = lcdc_offs_sublcd; 27693ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart num_channels++; 2770cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 2771cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2772cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2773cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27743ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (!num_channels) { 2775cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "no channels defined\n"); 2776cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm error = -EINVAL; 2777cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2778cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2779cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2780edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart /* for dual channel LCDC (MAIN + SUB) force shared format setting */ 27813ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (num_channels == 2) 2782edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart priv->forced_fourcc = pdata->ch[0].fourcc; 2783417d48274e755e537bae60461558c1f63a4e14deMagnus Damm 2784dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski priv->base = ioremap_nocache(res->start, resource_size(res)); 2785dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski if (!priv->base) 2786dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski goto err1; 2787dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski 27880a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart error = sh_mobile_lcdc_setup_clocks(priv, pdata->clock_source); 2789cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) { 2790cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "unable to setup clocks\n"); 2791cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2792cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2793cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27944774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart /* Enable runtime PM. */ 27954774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart pm_runtime_enable(&pdev->dev); 27967caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 27973ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart for (i = 0; i < num_channels; i++) { 27980707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; 2799c44f9f76d26c3b5158c65201d30e96393efe2fbdGuennadi Liakhovetski 28000707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart error = sh_mobile_lcdc_channel_init(ch); 2801cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) 28023ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart goto err1; 2803cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2804cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2805c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { 2806c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; 2807c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2808c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->cfg = &pdata->overlays[i]; 2809c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->channel = &priv->ch[0]; 2810c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 28110707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart error = sh_mobile_lcdc_overlay_init(ovl); 2812c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (error) 2813c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart goto err1; 2814c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2815c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2816cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm error = sh_mobile_lcdc_start(priv); 2817cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) { 2818cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "unable to start hardware\n"); 2819cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2820cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2821cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 28223ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart for (i = 0; i < num_channels; i++) { 28231c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt struct sh_mobile_lcdc_chan *ch = priv->ch + i; 28241c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt 2825a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart error = sh_mobile_lcdc_channel_fb_register(ch); 2826a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (error) 2827cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2828cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2829cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2830c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { 2831c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; 2832c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2833c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart error = sh_mobile_lcdc_overlay_fb_register(ovl); 2834c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (error) 2835c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart goto err1; 2836c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2837c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 28386011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* Failure ignored */ 28396011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski priv->notifier.notifier_call = sh_mobile_lcdc_notify; 28406011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski fb_register_client(&priv->notifier); 28416011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 2842cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return 0; 28438bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetskierr1: 2844cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm sh_mobile_lcdc_remove(pdev); 28458bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski 2846cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return error; 2847cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 2848cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2849cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic struct platform_driver sh_mobile_lcdc_driver = { 2850cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .driver = { 2851cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .name = "sh_mobile_lcdc_fb", 2852cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .owner = THIS_MODULE, 28532feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm .pm = &sh_mobile_lcdc_dev_pm_ops, 2854cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm }, 2855cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .probe = sh_mobile_lcdc_probe, 2856cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .remove = sh_mobile_lcdc_remove, 2857cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 2858cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 28594277f2c4667187cbbdd3da3be31ee681bc6b8300Axel Linmodule_platform_driver(sh_mobile_lcdc_driver); 2860cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2861cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus DammMODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver"); 2862cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus DammMODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); 2863cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus DammMODULE_LICENSE("GPL v2"); 2864