Mercurial > mplayer.hg
comparison drivers/radeon/radeon_vid.c @ 2870:f46c5556f1e6
radeon_vid: it's in first pre-alpha stage
Note: it's not public release and not test version.
It's simplest commit of unfinished and not working stuff
in hope to attract other developer to this driver.
(What is good: this driver is removable from driver list
and doesn't cause segfault !!!)
author | nick |
---|---|
date | Tue, 13 Nov 2001 17:20:47 +0000 |
parents | |
children | 3dd4e8a45d0d |
comparison
equal
deleted
inserted
replaced
2869:107d9e9e5bd1 | 2870:f46c5556f1e6 |
---|---|
1 /* | |
2 * | |
3 * radeon_vid.c | |
4 * | |
5 * Copyright (C) 2001 Nick Kurshev | |
6 * | |
7 * BES YUV Framebuffer driver for Radeon cards | |
8 * | |
9 * This software has been released under the terms of the GNU Public | |
10 * license. See http://www.gnu.org/copyleft/gpl.html for details. | |
11 * | |
12 * This file is partly based on mga_vid and sis_vid stuff from | |
13 * mplayer's package. | |
14 */ | |
15 | |
16 /* | |
17 It's entirely possible this major conflicts with something else | |
18 mknod /dev/radeon_vid c 178 0 | |
19 */ | |
20 | |
21 /* | |
22 TODO: | |
23 OV0_COLOUR_CNTL brightness saturation | |
24 SCALER_GAMMA_SEL_BRIGHT gamma correction ??? | |
25 OV0_GRAPHICS_KEY_CLR color key | |
26 OV0_AUTO_FLIP_CNTL | |
27 OV0_DEINTERLACE_PATTERN | |
28 OV0_FILTER_CNTL | |
29 OV0_VIDEO_KEY_CLR | |
30 OV0_KEY_CNTL | |
31 | |
32 BPP should be known | |
33 */ | |
34 | |
35 #include <linux/config.h> | |
36 #include <linux/version.h> | |
37 #include <linux/module.h> | |
38 #include <linux/types.h> | |
39 #include <linux/kernel.h> | |
40 #include <linux/sched.h> | |
41 #include <linux/mm.h> | |
42 #include <linux/string.h> | |
43 #include <linux/errno.h> | |
44 #include <linux/slab.h> | |
45 #include <linux/pci.h> | |
46 #include <linux/ioport.h> | |
47 #include <linux/init.h> | |
48 | |
49 #include "radeon_vid.h" | |
50 #include "radeon.h" | |
51 | |
52 #ifdef CONFIG_MTRR | |
53 #include <asm/mtrr.h> | |
54 #endif | |
55 | |
56 #include <asm/uaccess.h> | |
57 #include <asm/system.h> | |
58 #include <asm/io.h> | |
59 | |
60 #define TRUE 1 | |
61 #define FALSE 0 | |
62 | |
63 #define RADEON_VID_MAJOR 178 | |
64 | |
65 | |
66 MODULE_AUTHOR("Nick Kurshev <nickols_k@mail.ru>"); | |
67 MODULE_DESCRIPTION("Accelerated YUV BES driver for Radeons"); | |
68 MODULE_LICENSE("GPL"); | |
69 | |
70 | |
71 typedef struct bes_registers_s | |
72 { | |
73 /* base address of yuv framebuffer */ | |
74 uint32_t yuv_base; | |
75 uint32_t fourcc; | |
76 /* YUV BES registers */ | |
77 uint32_t reg_load_cntl; | |
78 uint32_t h_inc; | |
79 uint32_t step_by; | |
80 uint32_t y_x_start; | |
81 uint32_t y_x_end; | |
82 uint32_t v_inc; | |
83 uint32_t p1_blank_lines_at_top; | |
84 uint32_t vid_buf_pitch0_value; | |
85 uint32_t p1_x_start_end; | |
86 uint32_t p2_x_start_end; | |
87 uint32_t p3_x_start_end; | |
88 uint32_t vid_buf0_base_adrs; | |
89 /* These ones are for auto flip: maybe in the future */ | |
90 uint32_t vid_buf1_base_adrs; | |
91 uint32_t vid_buf2_base_adrs; | |
92 uint32_t vid_buf3_base_adrs; | |
93 uint32_t vid_buf4_base_adrs; | |
94 uint32_t vid_buf5_base_adrs; | |
95 | |
96 uint32_t p1_v_accum_init; | |
97 uint32_t p1_h_accum_init; | |
98 uint32_t p23_h_accum_init; | |
99 uint32_t scale_cntl; | |
100 uint32_t exclusive_horz; | |
101 uint32_t auto_flip_cntl; | |
102 uint32_t filter_cntl; | |
103 uint32_t colour_cntl; | |
104 uint32_t graphics_key_msk; | |
105 uint32_t graphics_key_clr; | |
106 uint32_t key_cntl; | |
107 uint32_t test; | |
108 } bes_registers_t; | |
109 | |
110 typedef struct video_registers_s | |
111 { | |
112 uint32_t name; | |
113 uint32_t value; | |
114 }video_registers_t; | |
115 | |
116 static bes_registers_t besr; | |
117 static video_registers_t vregs[] = | |
118 { | |
119 { OV0_REG_LOAD_CNTL, 0 }, | |
120 { OV0_H_INC, 0 }, | |
121 { OV0_STEP_BY, 0 }, | |
122 { OV0_Y_X_START, 0 }, | |
123 { OV0_Y_X_END, 0 }, | |
124 { OV0_V_INC, 0 }, | |
125 { OV0_P1_BLANK_LINES_AT_TOP, 0 }, | |
126 { OV0_VID_BUF_PITCH0_VALUE, 0 }, | |
127 { OV0_P1_X_START_END, 0 }, | |
128 { OV0_P2_X_START_END, 0 }, | |
129 { OV0_P3_X_START_END, 0 }, | |
130 { OV0_VID_BUF0_BASE_ADRS, 0 }, | |
131 { OV0_VID_BUF1_BASE_ADRS, 0 }, | |
132 { OV0_VID_BUF2_BASE_ADRS, 0 }, | |
133 { OV0_VID_BUF3_BASE_ADRS, 0 }, | |
134 { OV0_VID_BUF4_BASE_ADRS, 0 }, | |
135 { OV0_VID_BUF5_BASE_ADRS, 0 }, | |
136 { OV0_P1_V_ACCUM_INIT, 0 }, | |
137 { OV0_P1_H_ACCUM_INIT, 0 }, | |
138 { OV0_P23_H_ACCUM_INIT, 0 }, | |
139 { OV0_SCALE_CNTL, 0 }, | |
140 { OV0_EXCLUSIVE_HORZ, 0 }, | |
141 { OV0_AUTO_FLIP_CNTL, 0 }, | |
142 { OV0_FILTER_CNTL, 0 }, | |
143 { OV0_COLOUR_CNTL, 0 }, | |
144 { OV0_GRAPHICS_KEY_MSK, 0 }, | |
145 { OV0_GRAPHICS_KEY_CLR, 0 }, | |
146 { OV0_KEY_CNTL, 0 }, | |
147 { OV0_TEST, 0 } | |
148 }; | |
149 | |
150 static uint32_t radeon_vid_in_use = 0; | |
151 static uint32_t vid_src_ready = 0; | |
152 static uint32_t vid_overlay_on = 0; | |
153 | |
154 static uint8_t *radeon_mmio_base = 0; | |
155 static uint32_t radeon_mem_base = 0; | |
156 #define RADEON_SRC_BASE 0ULL /* this driver uses all video memory */ | |
157 | |
158 static uint32_t radeon_ram_size = 0; | |
159 | |
160 //static struct video_window radeon_win; | |
161 static mga_vid_config_t radeon_config; | |
162 | |
163 #define DEBUG 1 | |
164 #if DEBUG | |
165 #define RTRACE printk | |
166 #else | |
167 #define RTRACE(...) ((void)0) | |
168 #endif | |
169 | |
170 | |
171 /* | |
172 * IO macros | |
173 */ | |
174 | |
175 #define INREG8(addr) readb((radeon_mmio_base)+addr) | |
176 #define OUTREG8(addr,val) writeb(val, (radeon_mmio_base)+addr) | |
177 #define INREG(addr) readl((radeon_mmio_base)+addr) | |
178 #define OUTREG(addr,val) writel(val, (radeon_mmio_base)+addr) | |
179 | |
180 static void radeon_vid_save_state( void ) | |
181 { | |
182 size_t i; | |
183 for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++) | |
184 vregs[i].value = INREG(vregs[i].name); | |
185 } | |
186 | |
187 static void radeon_vid_restore_state( void ) | |
188 { | |
189 size_t i; | |
190 for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++) | |
191 OUTREG(vregs[i].name,vregs[i].value); | |
192 } | |
193 | |
194 static void radeon_vid_stop_video( void ) | |
195 { | |
196 if(vid_src_ready == 1) | |
197 { | |
198 OUTREG(OV0_SCALE_CNTL, SCALER_SOFT_RESET); | |
199 OUTREG(OV0_EXCLUSIVE_HORZ, 0); | |
200 OUTREG(OV0_AUTO_FLIP_CNTL, 0); /* maybe */ | |
201 OUTREG(OV0_FILTER_CNTL, 0x0000000f); | |
202 /* | |
203 OUTREG(OV0_COLOUR_CNTL, (brightness & 0x7f) | | |
204 (saturation << 8) | | |
205 (saturation << 16)); | |
206 OUTREG(OV0_GRAPHICS_KEY_MSK, (1 << depth) - 1); | |
207 OUTREG(OV0_GRAPHICS_KEY_CLR, colorKey); | |
208 */ | |
209 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_NE); | |
210 OUTREG(OV0_TEST, 0); | |
211 } | |
212 vid_src_ready = 0; | |
213 } | |
214 | |
215 static void radeon_vid_display_video( void ) | |
216 { | |
217 int bes_flags; | |
218 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK); | |
219 while(!(INREG(OV0_REG_LOAD_CNTL)®_LD_CTL_LOCK_READBACK)); | |
220 | |
221 OUTREG(OV0_AUTO_FLIP_CNTL,OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD); | |
222 | |
223 OUTREG(OV0_DEINTERLACE_PATTERN,0xAAAAA); | |
224 | |
225 OUTREG(OV0_AUTO_FLIP_CNTL,(INREG(OV0_AUTO_FLIP_CNTL)^OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE)); | |
226 OUTREG(OV0_AUTO_FLIP_CNTL,(INREG(OV0_AUTO_FLIP_CNTL)^OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE)); | |
227 | |
228 OUTREG(OV0_H_INC, besr.h_inc); | |
229 OUTREG(OV0_STEP_BY, besr.step_by); | |
230 OUTREG(OV0_Y_X_START, besr.y_x_start); | |
231 OUTREG(OV0_Y_X_END, besr.y_x_end); | |
232 OUTREG(OV0_V_INC, besr.v_inc); | |
233 OUTREG(OV0_P1_BLANK_LINES_AT_TOP, besr.p1_blank_lines_at_top); | |
234 OUTREG(OV0_VID_BUF_PITCH0_VALUE, besr.vid_buf_pitch0_value); | |
235 OUTREG(OV0_P1_X_START_END, besr.p1_x_start_end); | |
236 OUTREG(OV0_P2_X_START_END, besr.p2_x_start_end); | |
237 OUTREG(OV0_P3_X_START_END, besr.p3_x_start_end); | |
238 OUTREG(OV0_VID_BUF0_BASE_ADRS, besr.vid_buf0_base_adrs); | |
239 OUTREG(OV0_VID_BUF1_BASE_ADRS, besr.vid_buf1_base_adrs); | |
240 OUTREG(OV0_VID_BUF2_BASE_ADRS, besr.vid_buf2_base_adrs); | |
241 OUTREG(OV0_VID_BUF3_BASE_ADRS, besr.vid_buf3_base_adrs); | |
242 OUTREG(OV0_VID_BUF4_BASE_ADRS, besr.vid_buf4_base_adrs); | |
243 OUTREG(OV0_VID_BUF5_BASE_ADRS, besr.vid_buf5_base_adrs); | |
244 OUTREG(OV0_P1_V_ACCUM_INIT, besr.p1_v_accum_init); | |
245 OUTREG(OV0_P1_H_ACCUM_INIT, besr.p1_h_accum_init); | |
246 OUTREG(OV0_P23_H_ACCUM_INIT, besr.p23_h_accum_init); | |
247 | |
248 bes_flags = SCALER_ENABLE | | |
249 SCALER_DOUBLE_BUFFER | | |
250 SCALER_ADAPTIVE_DEINT | | |
251 SCALER_SMART_SWITCH | | |
252 SCALER_HORZ_PICK_NEAREST; | |
253 switch(besr.fourcc) | |
254 { | |
255 case IMGFMT_RGB15: | |
256 case IMGFMT_BGR15: bes_flags |= SCALER_SOURCE_15BPP; break; | |
257 case IMGFMT_RGB16: | |
258 case IMGFMT_BGR16: bes_flags |= SCALER_SOURCE_16BPP; break; | |
259 case IMGFMT_RGB24: | |
260 case IMGFMT_BGR24: bes_flags |= SCALER_SOURCE_24BPP; break; | |
261 case IMGFMT_RGB32: | |
262 case IMGFMT_BGR32: bes_flags |= SCALER_SOURCE_32BPP; break; | |
263 | |
264 case IMGFMT_YVU9: bes_flags |= SCALER_SOURCE_YUV9; break; | |
265 case IMGFMT_IYUV: bes_flags |= SCALER_SOURCE_YUV12; break; | |
266 case IMGFMT_UYVY: bes_flags |= SCALER_SOURCE_YVYU422; break; | |
267 | |
268 case IMGFMT_YV12: | |
269 case IMGFMT_I420: | |
270 case IMGFMT_YUY2: | |
271 default: bes_flags |= SCALER_SOURCE_VYUY422; break; | |
272 } | |
273 OUTREG(OV0_SCALE_CNTL, bes_flags); | |
274 /* | |
275 TODO: | |
276 brightness: -64 : +63 | |
277 saturation: 0 : 31 | |
278 OUTREG(OV0_COLOUR_CNTL, (brightness & 0x7f) | | |
279 (saturation << 8) | | |
280 (saturation << 16)); | |
281 OUTREG(OV0_GRAPHICS_KEY_CLR, colkey_red | colkey_green << 8 | colkey_blue << 16); | |
282 | |
283 */ | |
284 OUTREG(OV0_REG_LOAD_CNTL, 0); | |
285 } | |
286 | |
287 static void radeon_vid_start_video( void ) | |
288 { | |
289 if(vid_src_ready == 0) radeon_vid_display_video(); | |
290 vid_src_ready = 1; | |
291 } | |
292 | |
293 #define XXX_SRC_X 0 | |
294 #define XXX_SRC_Y 0 | |
295 | |
296 #define XXX_WIDTH config->dest_width | |
297 #define XXX_HEIGHT config->dest_height | |
298 | |
299 static int radeon_vid_init_video( mga_vid_config_t *config ) | |
300 { | |
301 uint32_t tmp,left,src_w,pitch; | |
302 | |
303 RTRACE("radeon_vid: usr_config: version = %x card=%x ram=%x src(%xx%x) dest(%x:%xx%x:%x) frame_size=%x num_frames=%x\n" | |
304 ,(uint32_t)config->version | |
305 ,(uint32_t)config->card_type | |
306 ,(uint32_t)config->ram_size | |
307 ,(uint32_t)config->src_width | |
308 ,(uint32_t)config->src_height | |
309 ,(uint32_t)config->x_org | |
310 ,(uint32_t)config->y_org | |
311 ,(uint32_t)config->dest_width | |
312 ,(uint32_t)config->dest_height | |
313 ,(uint32_t)config->frame_size | |
314 ,(uint32_t)config->num_frames); | |
315 | |
316 config->num_frames = 1; /* FIXME: should be 6 later */ | |
317 switch(config->format) | |
318 { | |
319 case IMGFMT_RGB15: | |
320 case IMGFMT_BGR15: | |
321 case IMGFMT_RGB16: | |
322 case IMGFMT_BGR16: | |
323 case IMGFMT_RGB24: | |
324 case IMGFMT_BGR24: | |
325 case IMGFMT_RGB32: | |
326 case IMGFMT_BGR32: | |
327 | |
328 case IMGFMT_YVU9: | |
329 case IMGFMT_IYUV: | |
330 case IMGFMT_UYVY: | |
331 | |
332 case IMGFMT_YV12: | |
333 case IMGFMT_I420: | |
334 case IMGFMT_YUY2: | |
335 break; | |
336 default: | |
337 printk( "radeon_vid: Unsupported pixel format: 0x%X\n",config->format); | |
338 return -1; | |
339 } | |
340 | |
341 pitch = ((XXX_WIDTH << 1) + 15) & ~15; | |
342 besr.fourcc = config->format; | |
343 | |
344 besr.v_inc = (config->src_height << 20) / (config->dest_height<<4); | |
345 besr.h_inc = (config->src_width << 12) / (config->dest_width<<4); | |
346 besr.step_by = 1; | |
347 | |
348 while(besr.h_inc >= (2 << 12)) { | |
349 besr.step_by++; | |
350 besr.h_inc >>= 1; | |
351 } | |
352 | |
353 RTRACE("radeon_vid: BES: v_inc=%x h_inc=%x step_by=%x\n",besr.v_inc,besr.h_inc,besr.step_by); | |
354 /* keep everything in 16.16 */ | |
355 | |
356 besr.vid_buf0_base_adrs = RADEON_SRC_BASE; /* I guess that offset 0 is o'k */ | |
357 /* besr.vid_buf0_base_adrs += (((XXX_SRC_X >> 16) & ~7) << 1)&0xfffffff0;*/ | |
358 RTRACE("radeon_vid: BES: vid_buf0_basey=%x\n",besr.vid_buf0_base_adrs); | |
359 besr.vid_buf1_base_adrs = besr.vid_buf0_base_adrs + config->frame_size; | |
360 besr.vid_buf2_base_adrs = besr.vid_buf0_base_adrs; | |
361 besr.vid_buf3_base_adrs = besr.vid_buf0_base_adrs + config->frame_size; | |
362 besr.vid_buf4_base_adrs = besr.vid_buf0_base_adrs; | |
363 besr.vid_buf5_base_adrs = besr.vid_buf0_base_adrs + config->frame_size; | |
364 | |
365 tmp = (XXX_SRC_X & 0x0003ffff) + 0x00028000 + (besr.h_inc << 3); | |
366 besr.p1_h_accum_init = ((tmp << 4) & 0x000f8000) | | |
367 ((tmp << 12) & 0xf0000000); | |
368 | |
369 tmp = ((XXX_SRC_X >> 1) & 0x0001ffff) + 0x00028000 + (besr.h_inc << 2); | |
370 besr.p23_h_accum_init = ((tmp << 4) & 0x000f8000) | | |
371 ((tmp << 12) & 0x70000000); | |
372 | |
373 tmp = (XXX_SRC_Y & 0x0000ffff) + 0x00018000; | |
374 besr.p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001; | |
375 | |
376 left = 0; /*(XXX_SRC_X >> 16) & 7;*/ | |
377 besr.h_inc |= ((besr.h_inc >> 1) << 16); | |
378 besr.step_by |= (besr.step_by << 8); | |
379 besr.y_x_start = (config->x_org + 8) | (config->y_org << 16); | |
380 besr.y_x_end = ((config->x_org + config->dest_width) + 8) | ((config->y_org + config->dest_height) << 16); | |
381 besr.p1_blank_lines_at_top = 0x00000fff | ((config->src_height - 1) << 16); | |
382 besr.vid_buf_pitch0_value = pitch; | |
383 RTRACE("radeon_vid: BES: y_x_start=%x y_x_end=%x blank_at_top=%x pitch0_value=%x\n" | |
384 ,besr.y_x_start,besr.y_x_end,besr.p1_blank_lines_at_top,besr.vid_buf_pitch0_value); | |
385 besr.p1_x_start_end = (config->src_width + left - 1) | (left << 16); | |
386 left >>= 1; src_w=config->src_width >> 1; | |
387 besr.p2_x_start_end = (src_w + left - 1) | (left << 16); | |
388 besr.p3_x_start_end = besr.p2_x_start_end; | |
389 return 0; | |
390 } | |
391 | |
392 static void radeon_vid_frame_sel(int frame) | |
393 { | |
394 /* TODO ASAP */ | |
395 } | |
396 | |
397 static int radeon_vid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | |
398 { | |
399 int frame; | |
400 | |
401 switch(cmd) | |
402 { | |
403 case MGA_VID_CONFIG: | |
404 RTRACE( "radeon_mmio_base = %p\n",radeon_mmio_base); | |
405 RTRACE( "radeon_mem_base = %08x\n",radeon_mem_base); | |
406 RTRACE( "radeon_vid: Received configuration\n"); | |
407 | |
408 if(copy_from_user(&radeon_config,(mga_vid_config_t*) arg,sizeof(mga_vid_config_t))) | |
409 { | |
410 printk( "radeon_vid: failed copy from userspace\n"); | |
411 return(-EFAULT); | |
412 } | |
413 if(radeon_config.version != MGA_VID_VERSION){ | |
414 printk( "radeon_vid: incompatible version! driver: %X requested: %X\n",MGA_VID_VERSION,radeon_config.version); | |
415 return(-EFAULT); | |
416 } | |
417 | |
418 if(radeon_config.frame_size==0 || radeon_config.frame_size>1024*768*2){ | |
419 printk( "radeon_vid: illegal frame_size: %d\n",radeon_config.frame_size); | |
420 return(-EFAULT); | |
421 } | |
422 | |
423 if(radeon_config.num_frames<1 || radeon_config.num_frames>4){ | |
424 printk( "radeon_vid: illegal num_frames: %d\n",radeon_config.num_frames); | |
425 return(-EFAULT); | |
426 } | |
427 | |
428 /* FIXME: Fake of G400 ;) or would be better G200 ??? */ | |
429 radeon_config.card_type = 0; | |
430 radeon_config.ram_size = radeon_ram_size; | |
431 | |
432 if (copy_to_user((mga_vid_config_t *) arg, &radeon_config, sizeof(mga_vid_config_t))) | |
433 { | |
434 printk( "radeon_vid: failed copy to userspace\n"); | |
435 return(-EFAULT); | |
436 } | |
437 return radeon_vid_init_video(&radeon_config); | |
438 break; | |
439 | |
440 case MGA_VID_ON: | |
441 RTRACE( "radeon_vid: Video ON (ioctl)\n"); | |
442 vid_src_ready = 1; | |
443 if(vid_overlay_on) radeon_vid_start_video(); | |
444 break; | |
445 | |
446 case MGA_VID_OFF: | |
447 RTRACE( "radeon_vid: Video OFF (ioctl)\n"); | |
448 radeon_vid_stop_video(); | |
449 break; | |
450 | |
451 case MGA_VID_FSEL: | |
452 if(copy_from_user(&frame,(int *) arg,sizeof(int))) | |
453 { | |
454 printk("radeon_vid: FSEL failed copy from userspace\n"); | |
455 return(-EFAULT); | |
456 } | |
457 radeon_vid_frame_sel(frame); | |
458 break; | |
459 | |
460 default: | |
461 printk( "radeon_vid: Invalid ioctl\n"); | |
462 return (-EINVAL); | |
463 } | |
464 | |
465 return 0; | |
466 } | |
467 | |
468 struct ati_card_id_s | |
469 { | |
470 int id; | |
471 char name[17]; | |
472 }ati_card_ids[]= | |
473 { | |
474 { PCI_DEVICE_ID_RADEON_QD, "Radeon QD " }, | |
475 { PCI_DEVICE_ID_RADEON_QE, "Radeon QE " }, | |
476 { PCI_DEVICE_ID_RADEON_QF, "Radeon QF " }, | |
477 { PCI_DEVICE_ID_RADEON_QG, "Radeon QG " }, | |
478 { PCI_DEVICE_ID_RADEON_QY, "Radeon VE QY " }, | |
479 { PCI_DEVICE_ID_RADEON_QZ, "Radeon VE QZ " }, | |
480 { PCI_DEVICE_ID_RADEON_LY, "Radeon M6 LY " }, | |
481 { PCI_DEVICE_ID_RADEON_LZ, "Radeon M6 LZ " }, | |
482 { PCI_DEVICE_ID_RADEON_LW, "Radeon M7 LW " }, | |
483 { PCI_DEVICE_ID_R200_QL, "Radeon2 8500 QL " }, | |
484 { PCI_DEVICE_ID_RV200_QW, "Radeon2 7500 QW " } | |
485 }; | |
486 | |
487 static int radeon_vid_config_card(void) | |
488 { | |
489 struct pci_dev *dev = NULL; | |
490 size_t i; | |
491 | |
492 for(i=0;i<sizeof(ati_card_ids)/sizeof(struct ati_card_id_s);i++) | |
493 if((dev=pci_find_device(PCI_VENDOR_ID_ATI, ati_card_ids[i].id, NULL))) | |
494 break; | |
495 if(dev) | |
496 printk("radeon_vid: Found %s\n",ati_card_ids[i].name); | |
497 else | |
498 { | |
499 printk("radeon_vid: No supported cards found\n"); | |
500 return FALSE; | |
501 } | |
502 | |
503 radeon_mmio_base = ioremap_nocache(pci_resource_start (dev, 2),RADEON_REGSIZE); | |
504 radeon_mem_base = dev->resource[0].start; | |
505 | |
506 RTRACE( "radeon_vid: MMIO at 0x%p\n", radeon_mmio_base); | |
507 RTRACE( "radeon_vid: Frame Buffer at 0x%08x\n", radeon_mem_base); | |
508 | |
509 radeon_ram_size = pci_resource_len(dev, 0)/0x100000; | |
510 | |
511 return TRUE; | |
512 } | |
513 | |
514 | |
515 static ssize_t radeon_vid_read(struct file *file, char *buf, size_t count, loff_t *ppos) | |
516 { | |
517 return -EINVAL; | |
518 } | |
519 | |
520 static ssize_t radeon_vid_write(struct file *file, const char *buf, size_t count, loff_t *ppos) | |
521 { | |
522 return -EINVAL; | |
523 } | |
524 | |
525 static int radeon_vid_mmap(struct file *file, struct vm_area_struct *vma) | |
526 { | |
527 | |
528 RTRACE( "radeon_vid: mapping video memory into userspace\n"); | |
529 if(remap_page_range(vma->vm_start, radeon_mem_base + RADEON_SRC_BASE, | |
530 vma->vm_end - vma->vm_start, vma->vm_page_prot)) | |
531 { | |
532 printk( "radeon_vid: error mapping video memory\n"); | |
533 return(-EAGAIN); | |
534 } | |
535 | |
536 return(0); | |
537 } | |
538 | |
539 static int radeon_vid_release(struct inode *inode, struct file *file) | |
540 { | |
541 //Close the window just in case | |
542 vid_src_ready = 0; | |
543 radeon_vid_in_use = 0; | |
544 radeon_vid_stop_video(); | |
545 | |
546 MOD_DEC_USE_COUNT; | |
547 return 0; | |
548 } | |
549 | |
550 static long long radeon_vid_lseek(struct file *file, long long offset, int origin) | |
551 { | |
552 return -ESPIPE; | |
553 } | |
554 | |
555 static int radeon_vid_open(struct inode *inode, struct file *file) | |
556 { | |
557 int minor = MINOR(inode->i_rdev); | |
558 | |
559 if(minor != 0) | |
560 return(-ENXIO); | |
561 | |
562 if(radeon_vid_in_use == 1) | |
563 return(-EBUSY); | |
564 | |
565 radeon_vid_in_use = 1; | |
566 MOD_INC_USE_COUNT; | |
567 return(0); | |
568 } | |
569 | |
570 #if LINUX_VERSION_CODE >= 0x020400 | |
571 static struct file_operations radeon_vid_fops = | |
572 { | |
573 llseek: radeon_vid_lseek, | |
574 read: radeon_vid_read, | |
575 write: radeon_vid_write, | |
576 ioctl: radeon_vid_ioctl, | |
577 mmap: radeon_vid_mmap, | |
578 open: radeon_vid_open, | |
579 release: radeon_vid_release | |
580 }; | |
581 #else | |
582 static struct file_operations radeon_vid_fops = | |
583 { | |
584 radeon_vid_lseek, | |
585 radeon_vid_read, | |
586 radeon_vid_write, | |
587 NULL, | |
588 NULL, | |
589 radeon_vid_ioctl, | |
590 radeon_vid_mmap, | |
591 radeon_vid_open, | |
592 NULL, | |
593 radeon_vid_release | |
594 }; | |
595 #endif | |
596 | |
597 /* | |
598 * Main Initialization Function | |
599 */ | |
600 | |
601 | |
602 static int radeon_vid_initialize(void) | |
603 { | |
604 radeon_vid_in_use = 0; | |
605 | |
606 RTRACE( "Radeon BES YUV Video interface v0.01 (c) Nick Kurshev\n"); | |
607 if(register_chrdev(RADEON_VID_MAJOR, "radeon_vid", &radeon_vid_fops)) | |
608 { | |
609 printk( "radeon_vid: unable to get major: %d\n", RADEON_VID_MAJOR); | |
610 return -EIO; | |
611 } | |
612 | |
613 if (!radeon_vid_config_card()) | |
614 { | |
615 printk("radeon_vid: can't configure this card\n"); | |
616 unregister_chrdev(RADEON_VID_MAJOR, "radeon_vid"); | |
617 return -EINVAL; | |
618 } | |
619 radeon_vid_save_state(); | |
620 return(0); | |
621 } | |
622 | |
623 int init_module(void) | |
624 { | |
625 return radeon_vid_initialize(); | |
626 } | |
627 | |
628 void cleanup_module(void) | |
629 { | |
630 radeon_vid_restore_state(); | |
631 if(radeon_mmio_base) | |
632 iounmap(radeon_mmio_base); | |
633 | |
634 RTRACE( "radeon_vid: Cleaning up module\n"); | |
635 unregister_chrdev(RADEON_VID_MAJOR, "radeon_vid"); | |
636 } | |
637 |