Tomasz Stanislawski | fef1c8d | 2011-02-02 05:40:08 -0300 | [diff] [blame^] | 1 | /* |
| 2 | * Samsung TV Mixer driver |
| 3 | * |
| 4 | * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. |
| 5 | * |
| 6 | * Tomasz Stanislawski, <t.stanislaws@samsung.com> |
| 7 | * |
| 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License as published |
| 10 | * by the Free Software Foundiation. either version 2 of the License, |
| 11 | * or (at your option) any later version |
| 12 | */ |
| 13 | |
| 14 | #ifndef SAMSUNG_MIXER_H |
| 15 | #define SAMSUNG_MIXER_H |
| 16 | |
| 17 | #ifdef CONFIG_VIDEO_SAMSUNG_S5P_MIXER_DEBUG |
| 18 | #define DEBUG |
| 19 | #endif |
| 20 | |
| 21 | #include <linux/fb.h> |
| 22 | #include <linux/kernel.h> |
| 23 | #include <linux/spinlock.h> |
| 24 | #include <linux/wait.h> |
| 25 | #include <media/v4l2-device.h> |
| 26 | #include <media/videobuf2-core.h> |
| 27 | |
| 28 | #include "regs-mixer.h" |
| 29 | |
| 30 | /** maximum number of output interfaces */ |
| 31 | #define MXR_MAX_OUTPUTS 2 |
| 32 | /** maximum number of input interfaces (layers) */ |
| 33 | #define MXR_MAX_LAYERS 3 |
| 34 | #define MXR_DRIVER_NAME "s5p-mixer" |
| 35 | /** maximal number of planes for every layer */ |
| 36 | #define MXR_MAX_PLANES 2 |
| 37 | |
| 38 | #define MXR_ENABLE 1 |
| 39 | #define MXR_DISABLE 0 |
| 40 | |
| 41 | /** description of a macroblock for packed formats */ |
| 42 | struct mxr_block { |
| 43 | /** vertical number of pixels in macroblock */ |
| 44 | unsigned int width; |
| 45 | /** horizontal number of pixels in macroblock */ |
| 46 | unsigned int height; |
| 47 | /** size of block in bytes */ |
| 48 | unsigned int size; |
| 49 | }; |
| 50 | |
| 51 | /** description of supported format */ |
| 52 | struct mxr_format { |
| 53 | /** format name/mnemonic */ |
| 54 | const char *name; |
| 55 | /** fourcc identifier */ |
| 56 | u32 fourcc; |
| 57 | /** colorspace identifier */ |
| 58 | enum v4l2_colorspace colorspace; |
| 59 | /** number of planes in image data */ |
| 60 | int num_planes; |
| 61 | /** description of block for each plane */ |
| 62 | struct mxr_block plane[MXR_MAX_PLANES]; |
| 63 | /** number of subframes in image data */ |
| 64 | int num_subframes; |
| 65 | /** specifies to which subframe belong given plane */ |
| 66 | int plane2subframe[MXR_MAX_PLANES]; |
| 67 | /** internal code, driver dependant */ |
| 68 | unsigned long cookie; |
| 69 | }; |
| 70 | |
| 71 | /** description of crop configuration for image */ |
| 72 | struct mxr_crop { |
| 73 | /** width of layer in pixels */ |
| 74 | unsigned int full_width; |
| 75 | /** height of layer in pixels */ |
| 76 | unsigned int full_height; |
| 77 | /** horizontal offset of first pixel to be displayed */ |
| 78 | unsigned int x_offset; |
| 79 | /** vertical offset of first pixel to be displayed */ |
| 80 | unsigned int y_offset; |
| 81 | /** width of displayed data in pixels */ |
| 82 | unsigned int width; |
| 83 | /** height of displayed data in pixels */ |
| 84 | unsigned int height; |
| 85 | /** indicate which fields are present in buffer */ |
| 86 | unsigned int field; |
| 87 | }; |
| 88 | |
| 89 | /** description of transformation from source to destination image */ |
| 90 | struct mxr_geometry { |
| 91 | /** cropping for source image */ |
| 92 | struct mxr_crop src; |
| 93 | /** cropping for destination image */ |
| 94 | struct mxr_crop dst; |
| 95 | /** layer-dependant description of horizontal scaling */ |
| 96 | unsigned int x_ratio; |
| 97 | /** layer-dependant description of vertical scaling */ |
| 98 | unsigned int y_ratio; |
| 99 | }; |
| 100 | |
| 101 | /** instance of a buffer */ |
| 102 | struct mxr_buffer { |
| 103 | /** common v4l buffer stuff -- must be first */ |
| 104 | struct vb2_buffer vb; |
| 105 | /** node for layer's lists */ |
| 106 | struct list_head list; |
| 107 | }; |
| 108 | |
| 109 | |
| 110 | /** internal states of layer */ |
| 111 | enum mxr_layer_state { |
| 112 | /** layers is not shown */ |
| 113 | MXR_LAYER_IDLE = 0, |
| 114 | /** state between STREAMON and hardware start */ |
| 115 | MXR_LAYER_STREAMING_START, |
| 116 | /** layer is shown */ |
| 117 | MXR_LAYER_STREAMING, |
| 118 | /** state before STREAMOFF is finished */ |
| 119 | MXR_LAYER_STREAMING_FINISH, |
| 120 | }; |
| 121 | |
| 122 | /** forward declarations */ |
| 123 | struct mxr_device; |
| 124 | struct mxr_layer; |
| 125 | |
| 126 | /** callback for layers operation */ |
| 127 | struct mxr_layer_ops { |
| 128 | /* TODO: try to port it to subdev API */ |
| 129 | /** handler for resource release function */ |
| 130 | void (*release)(struct mxr_layer *); |
| 131 | /** setting buffer to HW */ |
| 132 | void (*buffer_set)(struct mxr_layer *, struct mxr_buffer *); |
| 133 | /** setting format and geometry in HW */ |
| 134 | void (*format_set)(struct mxr_layer *); |
| 135 | /** streaming stop/start */ |
| 136 | void (*stream_set)(struct mxr_layer *, int); |
| 137 | /** adjusting geometry */ |
| 138 | void (*fix_geometry)(struct mxr_layer *); |
| 139 | }; |
| 140 | |
| 141 | /** layer instance, a single window and content displayed on output */ |
| 142 | struct mxr_layer { |
| 143 | /** parent mixer device */ |
| 144 | struct mxr_device *mdev; |
| 145 | /** layer index (unique identifier) */ |
| 146 | int idx; |
| 147 | /** callbacks for layer methods */ |
| 148 | struct mxr_layer_ops ops; |
| 149 | /** format array */ |
| 150 | const struct mxr_format **fmt_array; |
| 151 | /** size of format array */ |
| 152 | unsigned long fmt_array_size; |
| 153 | |
| 154 | /** lock for protection of list and state fields */ |
| 155 | spinlock_t enq_slock; |
| 156 | /** list for enqueued buffers */ |
| 157 | struct list_head enq_list; |
| 158 | /** buffer currently owned by hardware in temporary registers */ |
| 159 | struct mxr_buffer *update_buf; |
| 160 | /** buffer currently owned by hardware in shadow registers */ |
| 161 | struct mxr_buffer *shadow_buf; |
| 162 | /** state of layer IDLE/STREAMING */ |
| 163 | enum mxr_layer_state state; |
| 164 | |
| 165 | /** mutex for protection of fields below */ |
| 166 | struct mutex mutex; |
| 167 | /** handler for video node */ |
| 168 | struct video_device vfd; |
| 169 | /** queue for output buffers */ |
| 170 | struct vb2_queue vb_queue; |
| 171 | /** current image format */ |
| 172 | const struct mxr_format *fmt; |
| 173 | /** current geometry of image */ |
| 174 | struct mxr_geometry geo; |
| 175 | }; |
| 176 | |
| 177 | /** description of mixers output interface */ |
| 178 | struct mxr_output { |
| 179 | /** name of output */ |
| 180 | char name[32]; |
| 181 | /** output subdev */ |
| 182 | struct v4l2_subdev *sd; |
| 183 | /** cookie used for configuration of registers */ |
| 184 | int cookie; |
| 185 | }; |
| 186 | |
| 187 | /** specify source of output subdevs */ |
| 188 | struct mxr_output_conf { |
| 189 | /** name of output (connector) */ |
| 190 | char *output_name; |
| 191 | /** name of module that generates output subdev */ |
| 192 | char *module_name; |
| 193 | /** cookie need for mixer HW */ |
| 194 | int cookie; |
| 195 | }; |
| 196 | |
| 197 | struct clk; |
| 198 | struct regulator; |
| 199 | |
| 200 | /** auxiliary resources used my mixer */ |
| 201 | struct mxr_resources { |
| 202 | /** interrupt index */ |
| 203 | int irq; |
| 204 | /** pointer to Mixer registers */ |
| 205 | void __iomem *mxr_regs; |
| 206 | /** pointer to Video Processor registers */ |
| 207 | void __iomem *vp_regs; |
| 208 | /** other resources, should used under mxr_device.mutex */ |
| 209 | struct clk *mixer; |
| 210 | struct clk *vp; |
| 211 | struct clk *sclk_mixer; |
| 212 | struct clk *sclk_hdmi; |
| 213 | struct clk *sclk_dac; |
| 214 | }; |
| 215 | |
| 216 | /* event flags used */ |
| 217 | enum mxr_devide_flags { |
| 218 | MXR_EVENT_VSYNC = 0, |
| 219 | }; |
| 220 | |
| 221 | /** drivers instance */ |
| 222 | struct mxr_device { |
| 223 | /** master device */ |
| 224 | struct device *dev; |
| 225 | /** state of each layer */ |
| 226 | struct mxr_layer *layer[MXR_MAX_LAYERS]; |
| 227 | /** state of each output */ |
| 228 | struct mxr_output *output[MXR_MAX_OUTPUTS]; |
| 229 | /** number of registered outputs */ |
| 230 | int output_cnt; |
| 231 | |
| 232 | /* video resources */ |
| 233 | |
| 234 | /** V4L2 device */ |
| 235 | struct v4l2_device v4l2_dev; |
| 236 | /** context of allocator */ |
| 237 | void *alloc_ctx; |
| 238 | /** event wait queue */ |
| 239 | wait_queue_head_t event_queue; |
| 240 | /** state flags */ |
| 241 | unsigned long event_flags; |
| 242 | |
| 243 | /** spinlock for protection of registers */ |
| 244 | spinlock_t reg_slock; |
| 245 | |
| 246 | /** mutex for protection of fields below */ |
| 247 | struct mutex mutex; |
| 248 | /** number of entities depndant on output configuration */ |
| 249 | int n_output; |
| 250 | /** number of users that do streaming */ |
| 251 | int n_streamer; |
| 252 | /** index of current output */ |
| 253 | int current_output; |
| 254 | /** auxiliary resources used my mixer */ |
| 255 | struct mxr_resources res; |
| 256 | }; |
| 257 | |
| 258 | /** transform device structure into mixer device */ |
| 259 | static inline struct mxr_device *to_mdev(struct device *dev) |
| 260 | { |
| 261 | struct v4l2_device *vdev = dev_get_drvdata(dev); |
| 262 | return container_of(vdev, struct mxr_device, v4l2_dev); |
| 263 | } |
| 264 | |
| 265 | /** get current output data, should be called under mdev's mutex */ |
| 266 | static inline struct mxr_output *to_output(struct mxr_device *mdev) |
| 267 | { |
| 268 | return mdev->output[mdev->current_output]; |
| 269 | } |
| 270 | |
| 271 | /** get current output subdev, should be called under mdev's mutex */ |
| 272 | static inline struct v4l2_subdev *to_outsd(struct mxr_device *mdev) |
| 273 | { |
| 274 | struct mxr_output *out = to_output(mdev); |
| 275 | return out ? out->sd : NULL; |
| 276 | } |
| 277 | |
| 278 | /** forward declaration for mixer platform data */ |
| 279 | struct mxr_platform_data; |
| 280 | |
| 281 | /** acquiring common video resources */ |
| 282 | int __devinit mxr_acquire_video(struct mxr_device *mdev, |
| 283 | struct mxr_output_conf *output_cont, int output_count); |
| 284 | |
| 285 | /** releasing common video resources */ |
| 286 | void __devexit mxr_release_video(struct mxr_device *mdev); |
| 287 | |
| 288 | struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx); |
| 289 | struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx); |
| 290 | struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, |
| 291 | int idx, char *name, struct mxr_layer_ops *ops); |
| 292 | |
| 293 | void mxr_base_layer_release(struct mxr_layer *layer); |
| 294 | void mxr_layer_release(struct mxr_layer *layer); |
| 295 | |
| 296 | int mxr_base_layer_register(struct mxr_layer *layer); |
| 297 | void mxr_base_layer_unregister(struct mxr_layer *layer); |
| 298 | |
| 299 | unsigned long mxr_get_plane_size(const struct mxr_block *blk, |
| 300 | unsigned int width, unsigned int height); |
| 301 | |
| 302 | /** adds new consumer for mixer's power */ |
| 303 | int __must_check mxr_power_get(struct mxr_device *mdev); |
| 304 | /** removes consumer for mixer's power */ |
| 305 | void mxr_power_put(struct mxr_device *mdev); |
| 306 | /** add new client for output configuration */ |
| 307 | void mxr_output_get(struct mxr_device *mdev); |
| 308 | /** removes new client for output configuration */ |
| 309 | void mxr_output_put(struct mxr_device *mdev); |
| 310 | /** add new client for streaming */ |
| 311 | void mxr_streamer_get(struct mxr_device *mdev); |
| 312 | /** removes new client for streaming */ |
| 313 | void mxr_streamer_put(struct mxr_device *mdev); |
| 314 | /** returns format of data delivared to current output */ |
| 315 | void mxr_get_mbus_fmt(struct mxr_device *mdev, |
| 316 | struct v4l2_mbus_framefmt *mbus_fmt); |
| 317 | |
| 318 | /* Debug */ |
| 319 | |
| 320 | #define mxr_err(mdev, fmt, ...) dev_err(mdev->dev, fmt, ##__VA_ARGS__) |
| 321 | #define mxr_warn(mdev, fmt, ...) dev_warn(mdev->dev, fmt, ##__VA_ARGS__) |
| 322 | #define mxr_info(mdev, fmt, ...) dev_info(mdev->dev, fmt, ##__VA_ARGS__) |
| 323 | |
| 324 | #ifdef CONFIG_VIDEO_SAMSUNG_S5P_MIXER_DEBUG |
| 325 | #define mxr_dbg(mdev, fmt, ...) dev_dbg(mdev->dev, fmt, ##__VA_ARGS__) |
| 326 | #else |
| 327 | #define mxr_dbg(mdev, fmt, ...) do { (void) mdev; } while (0) |
| 328 | #endif |
| 329 | |
| 330 | /* accessing Mixer's and Video Processor's registers */ |
| 331 | |
| 332 | void mxr_vsync_set_update(struct mxr_device *mdev, int en); |
| 333 | void mxr_reg_reset(struct mxr_device *mdev); |
| 334 | irqreturn_t mxr_irq_handler(int irq, void *dev_data); |
| 335 | void mxr_reg_s_output(struct mxr_device *mdev, int cookie); |
| 336 | void mxr_reg_streamon(struct mxr_device *mdev); |
| 337 | void mxr_reg_streamoff(struct mxr_device *mdev); |
| 338 | int mxr_reg_wait4vsync(struct mxr_device *mdev); |
| 339 | void mxr_reg_set_mbus_fmt(struct mxr_device *mdev, |
| 340 | struct v4l2_mbus_framefmt *fmt); |
| 341 | void mxr_reg_graph_layer_stream(struct mxr_device *mdev, int idx, int en); |
| 342 | void mxr_reg_graph_buffer(struct mxr_device *mdev, int idx, dma_addr_t addr); |
| 343 | void mxr_reg_graph_format(struct mxr_device *mdev, int idx, |
| 344 | const struct mxr_format *fmt, const struct mxr_geometry *geo); |
| 345 | |
| 346 | void mxr_reg_vp_layer_stream(struct mxr_device *mdev, int en); |
| 347 | void mxr_reg_vp_buffer(struct mxr_device *mdev, |
| 348 | dma_addr_t luma_addr[2], dma_addr_t chroma_addr[2]); |
| 349 | void mxr_reg_vp_format(struct mxr_device *mdev, |
| 350 | const struct mxr_format *fmt, const struct mxr_geometry *geo); |
| 351 | void mxr_reg_dump(struct mxr_device *mdev); |
| 352 | |
| 353 | #endif /* SAMSUNG_MIXER_H */ |
| 354 | |