📄 zr36067.c
字号:
if (!zr->jpg_gbuf[i].frag_tab[2 * j]) break; mem_map_unreserve(MAP_NR (bus_to_virt (zr->jpg_gbuf[i]. frag_tab[2 * j]))); free_page((unsigned long) bus_to_virt(zr->jpg_gbuf[i]. frag_tab[2 * j])); zr->jpg_gbuf[i].frag_tab[2 * j] = 0; zr->jpg_gbuf[i].frag_tab[2 * j + 1] = 0; } } free_page((unsigned long) zr->jpg_gbuf[i].frag_tab); zr->jpg_gbuf[i].frag_tab = NULL; } zr->jpg_buffers_allocated = 0;}/* ----------------------------------------------------------------------- *//* I2C functions */#define I2C_DELAY 10/* software I2C functions */static void i2c_setlines(struct i2c_bus *bus, int ctrl, int data){ struct zoran *zr = (struct zoran *) bus->data; btwrite((data << 1) | ctrl, ZR36057_I2CBR); udelay(I2C_DELAY);}static int i2c_getdataline(struct i2c_bus *bus){ struct zoran *zr = (struct zoran *) bus->data; return (btread(ZR36057_I2CBR) >> 1) & 1;}static void attach_inform(struct i2c_bus *bus, int id){ int i; struct zoran *zr = (struct zoran *) bus->data; DEBUG1(printk(KERN_DEBUG "%s: i2c attach %02x\n", zr->name, id)); for (i = 0; i < bus->devcount; i++) { if (strcmp(bus->devices[i]->name, "saa7110") == 0) { if (zr->revision < 2) { zr->card = DC10; sprintf(zr->name, "DC10[%u]", zr->id); } else { zr->card = DC10plus; sprintf(zr->name, "DC10plus[%u]", zr->id); } break; } if (strcmp(bus->devices[i]->name, "bt819") == 0) { zr->card = LML33; sprintf(zr->name, "LML33[%u]", zr->id); break; } if (strcmp(bus->devices[i]->name, "saa7111") == 0) { zr->card = BUZ; sprintf(zr->name, "Buz[%u]", zr->id); break; } }}static void detach_inform(struct i2c_bus *bus, int id){ DEBUG1(struct zoran *zr = (struct zoran *) bus->data); DEBUG1(printk(KERN_DEBUG "%s: i2c detach %02x\n", zr->name, id));}static struct i2c_bus zoran_i2c_bus_template = { "zr36057", I2C_BUSID_BT848, NULL, SPIN_LOCK_UNLOCKED, attach_inform, detach_inform, i2c_setlines, i2c_getdataline, NULL, NULL,};/* * Set the registers for the size we have specified. Don't bother * trying to understand this without the ZR36057 manual in front of * you [AC]. * * PS: The manual is free for download in .pdf format from * www.zoran.com - nicely done those folks. */static struct tvnorm f50sqpixel = { 944, 768, 83, 880, 625, 576, 16 };static struct tvnorm f60sqpixel = { 780, 640, 51, 716, 525, 480, 12 };static struct tvnorm f50ccir601 = { 864, 720, 75, 804, 625, 576, 18 };static struct tvnorm f60ccir601 = { 858, 720, 57, 788, 525, 480, 16 };static struct tvnorm *dc10norms[] = { &f50sqpixel, /* PAL-BDGHI */ &f60sqpixel, /* NTSC */ &f50sqpixel, /* SECAM */};static struct tvnorm *lml33norms[] = { &f50ccir601, /* PAL-BDGHI */ &f60ccir601, /* NTSC */ NULL, /* SECAM (not supported in LML33) */};static struct tvnorm *buznorms[] = { &f50ccir601, /* PAL-BDGHI */ &f60ccir601, /* NTSC */ NULL, /* SECAM */};static struct tvnorm *unsupported[] = { NULL, /* PAL-BDGHI */ NULL, /* NTSC */ NULL, /* SECAM */};static struct tvnorm **cardnorms[] = { unsupported, /* UNKNOWN */ dc10norms, /* DC10 */ dc10norms, /* DC10plus */ lml33norms, /* LML33 */ buznorms, /* Buz */};static u32 cardvsync[] = { 0, /* UNKNOWN */ ZR36057_ISR_GIRQ1, /* DC10 */ ZR36057_ISR_GIRQ1, /* DC10plus */ ZR36057_ISR_GIRQ0, /* LML33 */ ZR36057_ISR_GIRQ0, /* Buz */};static u32 cardjpegint[] = { 0, /* UNKNOWN */ ZR36057_ISR_GIRQ0, /* DC10 */ ZR36057_ISR_GIRQ0, /* DC10plus */ ZR36057_ISR_GIRQ1, /* LML33 */ ZR36057_ISR_GIRQ1, /* Buz */};static int format2bpp(int format){ int bpp; /* Determine the number of bytes per pixel for the video format requested */ switch (format) { case VIDEO_PALETTE_YUV422: bpp = 2; break; case VIDEO_PALETTE_RGB555: bpp = 2; break; case VIDEO_PALETTE_RGB565: bpp = 2; break; case VIDEO_PALETTE_RGB24: bpp = 3; break; case VIDEO_PALETTE_RGB32: bpp = 4; break; default: bpp = 0; } return bpp;}static void zr36057_adjust_vfe(struct zoran *zr, enum zoran_codec_mode mode){ u32 reg; switch (mode) { case BUZ_MODE_MOTION_DECOMPRESS: btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR); reg = btread(ZR36057_VFEHCR); if (reg & (1 << 10)) { reg += ((1 << 10) | 1); } btwrite(reg, ZR36057_VFEHCR); break; case BUZ_MODE_MOTION_COMPRESS: case BUZ_MODE_IDLE: default: if (zr->params.norm == VIDEO_MODE_NTSC) btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR); else btor(ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR); reg = btread(ZR36057_VFEHCR); if (!(reg & (1 << 10))) { reg -= ((1 << 10) | 1); } btwrite(reg, ZR36057_VFEHCR); break; }}/* * set geometry */static void zr36057_set_vfe(struct zoran *zr, int video_width, int video_height, unsigned int video_format){ struct tvnorm *tvn; unsigned HStart, HEnd, VStart, VEnd; unsigned DispMode; unsigned VidWinWid, VidWinHt; unsigned hcrop1, hcrop2, vcrop1, vcrop2; unsigned Wa, We, Ha, He; unsigned X, Y, HorDcm, VerDcm; u32 reg; unsigned mask_line_size; tvn = zr->timing; Wa = tvn->Wa; Ha = tvn->Ha; DEBUG1(printk (BUZ_INFO ": width = %d, height = %d\n", video_width, video_height)); if (zr->params.norm != VIDEO_MODE_PAL && zr->params.norm != VIDEO_MODE_NTSC && zr->params.norm != VIDEO_MODE_SECAM) { printk(KERN_ERR "%s: set_vfe: video_norm = %d not valid\n", zr->name, zr->params.norm); return; } if (video_width < BUZ_MIN_WIDTH || video_height < BUZ_MIN_HEIGHT || video_width > Wa || video_height > Ha) { printk(KERN_ERR "%s: set_vfe: w=%d h=%d not valid\n", zr->name, video_width, video_height); return; } /* if window has more than half of active height, switch on interlacing - we want the full information */ zr->video_interlace = (video_height > Ha / 2); /**** zr36057 ****/ /* horizontal */ VidWinWid = video_width; X = (VidWinWid * 64 + tvn->Wa - 1) / tvn->Wa; We = (VidWinWid * 64) / X; HorDcm = 64 - X; hcrop1 = 2 * ((tvn->Wa - We) / 4); hcrop2 = tvn->Wa - We - hcrop1; HStart = tvn->HStart | 1; if (zr->card == LML33) HStart += 62; if (zr->card == BUZ) { //HStart += 67; HStart += 44; } HEnd = HStart + tvn->Wa - 1; HStart += hcrop1; HEnd -= hcrop2; reg = ((HStart & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HStart) | ((HEnd & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HEnd); if (zr->card != BUZ) reg |= ZR36057_VFEHCR_HSPol; btwrite(reg, ZR36057_VFEHCR); /* Vertical */ DispMode = !zr->video_interlace; VidWinHt = DispMode ? video_height : video_height / 2; Y = (VidWinHt * 64 * 2 + tvn->Ha - 1) / tvn->Ha; He = (VidWinHt * 64) / Y; VerDcm = 64 - Y; vcrop1 = (tvn->Ha / 2 - He) / 2; vcrop2 = tvn->Ha / 2 - He - vcrop1; VStart = tvn->VStart; VEnd = VStart + tvn->Ha / 2 - 1; VStart += vcrop1; VEnd -= vcrop2; reg = ((VStart & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VStart) | ((VEnd & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VEnd); reg |= ZR36057_VFEVCR_VSPol; btwrite(reg, ZR36057_VFEVCR); /* scaler and pixel format */ reg = 0; reg |= (HorDcm << ZR36057_VFESPFR_HorDcm); reg |= (VerDcm << ZR36057_VFESPFR_VerDcm); reg |= (DispMode << ZR36057_VFESPFR_DispMode); reg |= ZR36057_VFESPFR_LittleEndian; /* RJ: I don't know, why the following has to be the opposite of the corresponding ZR36060 setting, but only this way we get the correct colors when uncompressing to the screen */ //reg |= ZR36057_VFESPFR_VCLKPol; /**/ /* RJ: Don't know if that is needed for NTSC also */ if (zr->params.norm != VIDEO_MODE_NTSC) reg |= ZR36057_VFESPFR_ExtFl; // NEEDED!!!!!!! Wolfgang reg |= ZR36057_VFESPFR_TopField; switch (video_format) { case VIDEO_PALETTE_YUV422: reg |= ZR36057_VFESPFR_YUV422; break; case VIDEO_PALETTE_RGB555: reg |= ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ErrDif; break; case VIDEO_PALETTE_RGB565: reg |= ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ErrDif; break; case VIDEO_PALETTE_RGB24: reg |= ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_Pack24; break; case VIDEO_PALETTE_RGB32: reg |= ZR36057_VFESPFR_RGB888; break; default: printk(KERN_INFO "%s: Unknown color_fmt=%x\n", zr->name, video_format); return; } if (HorDcm >= 48) { reg |= 3 << ZR36057_VFESPFR_HFilter; /* 5 tap filter */ } else if (HorDcm >= 32) { reg |= 2 << ZR36057_VFESPFR_HFilter; /* 4 tap filter */ } else if (HorDcm >= 16) { reg |= 1 << ZR36057_VFESPFR_HFilter; /* 3 tap filter */ } btwrite(reg, ZR36057_VFESPFR); /* display configuration */ reg = (16 << ZR36057_VDCR_MinPix) | (VidWinHt << ZR36057_VDCR_VidWinHt) | (VidWinWid << ZR36057_VDCR_VidWinWid); if (triton || zr->revision <= 1) reg &= ~ZR36057_VDCR_Triton; else reg |= ZR36057_VDCR_Triton; btwrite(reg, ZR36057_VDCR); /* Write overlay clipping mask data, but don't enable overlay clipping */ /* RJ: since this makes only sense on the screen, we use zr->window.width instead of video_width */ mask_line_size = (BUZ_MAX_WIDTH + 31) / 32; reg = virt_to_bus(zr->overlay_mask); btwrite(reg, ZR36057_MMTR); reg = virt_to_bus(zr->overlay_mask + mask_line_size); btwrite(reg, ZR36057_MMBR); reg = mask_line_size - (zr->window.width + 31) / 32; if (DispMode == 0) reg += mask_line_size; reg <<= ZR36057_OCR_MaskStride; btwrite(reg, ZR36057_OCR); zr36057_adjust_vfe(zr, zr->codec_mode);}/* * Switch overlay on or off */static void zr36057_overlay(struct zoran *zr, int on){ int fmt, bpp; u32 reg; if (on) { /* do the necessary settings ... */ btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); /* switch it off first */ switch (zr->buffer.depth) { case 15: fmt = VIDEO_PALETTE_RGB555; bpp = 2; break; case 16: fmt = VIDEO_PALETTE_RGB565; bpp = 2; break; case 24: fmt = VIDEO_PALETTE_RGB24; bpp = 3; break; case 32: fmt = VIDEO_PALETTE_RGB32; bpp = 4; break; default: fmt = 0; bpp = 0; } zr36057_set_vfe(zr, zr->window.width, zr->window.height, fmt); /* Start and length of each line MUST be 4-byte aligned. This should be allready checked before the call to this routine. All error messages are internal driver checking only! */ /* video display top and bottom registers */ reg = (u32) zr->buffer.base + zr->window.x * bpp + zr->window.y * zr->buffer.bytesperline; btwrite(reg, ZR36057_VDTR); if (reg & 3) printk(KERN_ERR "%s: zr36057_overlay: video_address not aligned\n", zr->name); if (zr->video_interlace) reg += zr->buffer.bytesperline; btwrite(reg, ZR36057_VDBR); /* video stride, status, and frame grab register */ reg = zr->buffer.bytesperline - zr->window.width * bpp; if (zr->video_interlace) reg += zr->buffer.bytesperline; if (reg & 3) printk(KERN_ERR "%s: zr36057_overlay: video_stride not aligned\n", zr->name); reg = (reg << ZR36057_VSSFGR_DispStride); reg |= ZR36057_VSSFGR_VidOvf; /* clear overflow status */ btwrite(reg, ZR36057_VSSFGR); /* Set overlay clipping */ if (zr->window.clipcount) btor(ZR36057_OCR_OvlEnable, ZR36057_OCR); /* ... and switch it on */ btor(ZR36057_VDCR_VidEn, ZR36057_VDCR); } else { /* Switch it off */ btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); }}/* * The overlay mask has one bit for each pixel on a scan line, * and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels. */static void write_overlay_mask(struct zoran *zr, struct video_clip *vp, int count){ unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32; u32 *mask; int x, y, width, height; unsigned i, j, k; u32 reg; /* fill mask with one bits */ memset(zr->overlay_mask, ~0, mask_line_size * 4 * BUZ_MAX_HEIGHT); reg = 0; for (i = 0; i < count; ++i) { /* pick up local copy of clip */ x = vp[i].x; y = vp[i].y; width = vp[i].width; height = vp[i].height; /* trim clips that extend beyond the window */ if (x < 0) { width += x; x = 0; } if (y < 0) { height += y; y = 0; } if (x + width > zr->window.width) { width = zr->window.width - x; } if (y + height > zr->window.height) { height = zr->window.height - y; } /* ignore degenerate clips */ if (height <= 0) { continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -