static int snd_em8300_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	em8300_alsa_t *em8300_alsa = snd_pcm_substream_chip(substream);
	struct em8300_s *em = em8300_alsa->em;
//	snd_pcm_runtime_t *runtime = substream->runtime;
//	printk("em8300-%d: snd_em8300_pcm_trigger(%d) called.\n", em->instance, cmd);
	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		em8300_alsa->indirect.hw_io =
		em8300_alsa->indirect.hw_data =
			((read_ucregister(MA_Rdptr_Hi) << 16)
			| read_ucregister(MA_Rdptr)) & ~3;
		snd_em8300_pcm_ack(substream);
		em->irqmask |= IRQSTATUS_AUDIO_FIFO;
		write_ucregister(Q_IrqMask, em->irqmask);
		mpegaudio_command(em, MACOMMAND_PLAY);
		break;
	case SNDRV_PCM_TRIGGER_STOP:
		em->irqmask &= ~IRQSTATUS_AUDIO_FIFO;
		write_ucregister(Q_IrqMask, em->irqmask);
		mpegaudio_command(em, MACOMMAND_STOP);
		break;
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		mpegaudio_command(em, MACOMMAND_PAUSE);
		break;
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		mpegaudio_command(em, MACOMMAND_PLAY);
		break;
	default:
		return -EINVAL;
	}
	return 0;
}
Beispiel #2
0
int em8300_dicom_get_dbufinfo(struct em8300_s *em)
{
	int displaybuffer;
	struct displaybuffer_info_s *di = &em->dbuf_info;

	displaybuffer = read_ucregister(DICOM_DisplayBuffer) + 0x1000;

	di->xsize = read_register(displaybuffer);
	di->ysize = read_register(displaybuffer+1);
	di->xsize2 = read_register(displaybuffer+2) & 0xfff;
	di->flag1 = read_register(displaybuffer+2) & 0x8000;
	di->flag2 = read_ucregister(Vsync_DBuf) & 0x4000;

	if (read_ucregister(MicroCodeVersion) <= 0xf) {
		di->buffer1 = (read_register(displaybuffer + 3) | (read_register(displaybuffer + 4) << 16)) << 4;
		di->buffer2 = (read_register(displaybuffer + 5) | (read_register(displaybuffer + 6) << 16)) << 4;
	} else {
		di->buffer1 = read_register(displaybuffer + 3) << 6;
		di->buffer2 = read_register(displaybuffer + 4) << 6;
	}

	if (displaybuffer == ucregister(Width_Buf3)) {
		di->unk_present = 1;
		if(read_ucregister(MicroCodeVersion) <= 0xf) {
			di->unknown1 = read_register(displaybuffer + 7);
			di->unknown2 = (read_register(displaybuffer + 8) | (read_register(displaybuffer + 9) << 16)) << 4;
			di->unknown3 = (read_register(displaybuffer + 0xa) | (read_register(displaybuffer + 0xb) << 16)) << 4;
		} else {
			di->unknown2 = read_register(displaybuffer + 6);
			di->unknown3 = read_register(displaybuffer + 7);
		}
	} else {
		di->unk_present = 0;
	}

	pr_debug("em8300-%d: DICOM buffer: xsize=0x%x(%d)\n", em->card_nr, di->xsize, di->xsize);
	pr_debug("em8300-%d:               ysize=0x%x(%d)\n", em->card_nr, di->ysize, di->ysize);
	pr_debug("em8300-%d:               xsize2=0x%x(%d)\n", em->card_nr, di->xsize2, di->xsize2);
	pr_debug("em8300-%d:               flag1=%d, flag2=%d\n", em->card_nr, di->flag1, di->flag2);
	pr_debug("em8300-%d:               buffer1=0x%x(%d)\n", em->card_nr, di->buffer1, di->buffer1);
	pr_debug("em8300-%d:               buffer2=0x%x(%d)\n", em->card_nr, di->buffer2, di->buffer2);

	if (di->unk_present) {
		pr_debug("em8300-%d:               unknown1=0x%x(%d)\n", em->card_nr, di->unknown1, di->unknown1);
		pr_debug("em8300-%d:               unknown2=0x%x(%d)\n", em->card_nr, di->unknown2, di->unknown2);
		pr_debug("em8300-%d:               unknown3=0x%x(%d)\n", em->card_nr, di->unknown3, di->unknown3);
	}
	return 0;
}
Beispiel #3
0
void em8300_dicom_setBCS(struct em8300_s *em, int brightness, int contrast, int saturation)
{
	int luma_factor, luma_offset, chroma_factor;
	em->dicom_brightness = brightness;
	em->dicom_contrast = contrast;
	em->dicom_saturation = saturation;

	if (read_ucregister(DICOM_UpdateFlag) == 1) {
		write_ucregister(DICOM_UpdateFlag, 0);
		udelay(1);
	}

	luma_factor = (contrast * 127 + 500) / 1000;
	luma_offset = 128 - 2 * luma_factor + ((brightness - 500) * 255 + 500) / 1000;
	if (luma_offset < -128)
		luma_offset = -128;
	if (luma_offset > 127)
		luma_offset = 127;
	chroma_factor = (luma_factor * saturation + 250) / 500;
	if (chroma_factor > 127)
		chroma_factor = 127;

	write_ucregister(DICOM_BCSLuma,
			 ((luma_factor & 255) << 8) | (luma_offset & 255));
	write_ucregister(DICOM_BCSChroma,
			 ((chroma_factor & 255) << 8) | (chroma_factor & 255));

	write_ucregister(DICOM_UpdateFlag, 1);
}
static snd_pcm_uframes_t snd_em8300_pcm_pointer(struct snd_pcm_substream *substream)
{
//	snd_pcm_runtime_t *runtime = substream->runtime;
	em8300_alsa_t *em8300_alsa = snd_pcm_substream_chip(substream);
	struct em8300_s *em = em8300_alsa->em;
	unsigned int hw_ptr =
		((read_ucregister(MA_Rdptr_Hi) << 16)
		 | read_ucregister(MA_Rdptr)) & ~3;
//	snd_pcm_uframes_t ret = snd_pcm_indirect_playback_pointer(substream,
//								  &em8300_alsa->indirect,
//								  hw_ptr);
//	printk("em8300-%d: snd_em8300_pcm_pointer called: %d\n", em->instance, ret);
//	return ret;
	return snd_em8300_pcm_indirect_playback_pointer(substream,
							&em8300_alsa->indirect,
							hw_ptr);
}
static int snd_em8300_pcm_prepare(struct snd_pcm_substream *substream)
{
	em8300_alsa_t *em8300_alsa = snd_pcm_substream_chip(substream);
	struct em8300_s *em = em8300_alsa->em;
	struct snd_pcm_runtime *runtime = substream->runtime;
//	printk("em8300-%d: snd_em8300_pcm_prepare called.\n", em->instance);

	em->clockgen &= ~CLOCKGEN_SAMPFREQ_MASK;
	switch (runtime->rate) {
	case 48000:
//		printk("em8300-%d: runtime->rate set to 48000\n", em->instance);
		em->clockgen |= CLOCKGEN_SAMPFREQ_48;
		break;
	case 44100:
//		printk("em8300-%d: runtime->rate set to 44100\n", em->instance);
		em->clockgen |= CLOCKGEN_SAMPFREQ_44;
		break;
	case 32000:
//		printk("em8300-%d: runtime->rate set to 32000\n", em->instance);
		em->clockgen |= CLOCKGEN_SAMPFREQ_32;
		break;
	default:
//		printk("em8300-%d: bad runtime->rate\n", em->instance);
		em->clockgen |= CLOCKGEN_SAMPFREQ_48;
	}
	em8300_clockgen_write(em, em->clockgen);

	memset(&em8300_alsa->indirect, 0, sizeof(em8300_alsa->indirect));
	em8300_alsa->indirect.hw_buffer_size =
		(read_ucregister(MA_BuffSize_Hi) << 16)
		| read_ucregister(MA_BuffSize);
	em8300_alsa->indirect.sw_buffer_size =
		snd_pcm_lib_buffer_bytes(substream);

	write_ucregister(MA_PCIRdPtr, ucregister(MA_PCIStart) - 0x1000);
	write_ucregister(MA_PCIWrPtr, ucregister(MA_PCIStart) - 0x1000);

	return 0;
}
static void snd_em8300_pcm_trans_dma(struct snd_pcm_substream *substream,
				     snd_em8300_pcm_indirect_t *rec,
				     size_t bytes)
{
//	snd_pcm_runtime_t *runtime = substream->runtime;
	em8300_alsa_t *em8300_alsa = snd_pcm_substream_chip(substream);
	struct em8300_s *em = em8300_alsa->em;
	int writeindex = ((int)read_ucregister(MA_PCIWrPtr) - (ucregister(MA_PCIStart) - 0x1000)) / 3;
	int readindex = ((int)read_ucregister(MA_PCIRdPtr) - (ucregister(MA_PCIStart) - 0x1000)) / 3;
	writel((unsigned long int)(substream->runtime->dma_addr + rec->sw_data) >> 16,
	       ((uint32_t *)ucregister_ptr(MA_PCIStart))+3*writeindex);
	writel((unsigned long int)(substream->runtime->dma_addr + rec->sw_data) & 0xffff,
	       ((uint32_t *)ucregister_ptr(MA_PCIStart))+3*writeindex+1);
	writel(bytes,
	       ((uint32_t *)ucregister_ptr(MA_PCIStart))+3*writeindex+2);
	writeindex += 1;
	writeindex %= read_ucregister(MA_PCISize) / 3;
//	printk("em8300-%d: snd_em8300_pcm_trans_dma(%d) called.\n", em->instance, bytes);
	if (readindex != writeindex)
		write_ucregister(MA_PCIWrPtr, ucregister(MA_PCIStart) - 0x1000 + writeindex * 3);
	else
		printk("em8300-%d: snd_em8300_pcm_trans_dma failed.\n", em->instance);
}
Beispiel #7
0
int em8300_control_ioctl(struct em8300_s *em, int cmd, unsigned long arg)
{
	em8300_register_t reg;
	int val, len;
	em8300_bcs_t bcs;
	em8300_overlay_window_t ov_win;
	em8300_overlay_screen_t ov_scr;
	em8300_overlay_calibrate_t ov_cal;
	em8300_attribute_t attr;
	int old_count;
	long ret;

	if (_IOC_DIR(cmd) != 0) {
		len = _IOC_SIZE(cmd);

		if (len < 1 || len > 65536 || arg == 0) {
			return -EFAULT;
		}
		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			if (!access_ok(VERIFY_READ, (void *) arg, len)) {
				return -EFAULT;
			}
		}
		if (_IOC_DIR(cmd) & _IOC_READ) {
			if (!access_ok(VERIFY_WRITE, (void *) arg, len)) {
				return -EFAULT;
			}
		}
	}

	switch (_IOC_NR(cmd)) {
	case _IOC_NR(EM8300_IOCTL_INIT):
		return em8300_ioctl_init(em, (em8300_microcode_t *) arg);

	case _IOC_NR(EM8300_IOCTL_WRITEREG):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (copy_from_user(&reg, (void *) arg, sizeof(em8300_register_t)))
			return -EFAULT;

		if (reg.microcode_register) {
			write_ucregister(reg.reg, reg.val);
		} else {
			write_register(reg.reg, reg.val);
		}
		break;

	case _IOC_NR(EM8300_IOCTL_READREG):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (copy_from_user(&reg, (void *) arg, sizeof(em8300_register_t)))
			return -EFAULT;

		if (reg.microcode_register) {
			reg.val = read_ucregister(reg.reg);
			reg.reg = ucregister(reg.reg);
		} else {
			reg.val = read_register(reg.reg);
		}
		if (copy_to_user((void *) arg, &reg, sizeof(em8300_register_t)))
			return -EFAULT;
		break;

	case _IOC_NR(EM8300_IOCTL_VBI):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		old_count = em->irqcount;
		em->irqmask |= IRQSTATUS_VIDEO_VBL;
		write_ucregister(Q_IrqMask, em->irqmask);

		ret = wait_event_interruptible_timeout(em->vbi_wait, em->irqcount != old_count, HZ);
		if (ret == 0)
			return -EINTR;
		else if (ret < 0)
			return ret;

		/* copy timestamp and return */
		if (copy_to_user((void *) arg, &em->tv, sizeof(struct timeval)))
			return -EFAULT;
		return 0;

	case _IOC_NR(EM8300_IOCTL_GETBCS):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			if (copy_from_user(&bcs, (void *) arg, sizeof(em8300_bcs_t)))
				return -EFAULT;
			em8300_dicom_setBCS(em, bcs.brightness, bcs.contrast, bcs.saturation);
		}

		if (_IOC_DIR(cmd) & _IOC_READ) {
			bcs.brightness = em->dicom_brightness;
			bcs.contrast = em->dicom_contrast;
			bcs.saturation = em->dicom_saturation;
			if (copy_to_user((void *) arg, &bcs, sizeof(em8300_bcs_t)))
				return -EFAULT;
		}
		break;

	case _IOC_NR(EM8300_IOCTL_SET_VIDEOMODE):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			get_user(val, (int *) arg);
			return em8300_ioctl_setvideomode(em, val);
		}

		if (_IOC_DIR(cmd) & _IOC_READ) {
			if (copy_to_user((void *) arg, &em->video_mode, sizeof(em->video_mode)))
				return -EFAULT;
		}
		break;

	case _IOC_NR(EM8300_IOCTL_SET_PLAYMODE):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			get_user(val, (int *) arg);
			return em8300_ioctl_setplaymode(em, val);
		}
		break;

	case _IOC_NR(EM8300_IOCTL_SET_ASPECTRATIO):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			get_user(val, (int *) arg);
			em8300_ioctl_setaspectratio(em, val);
		}

		if (_IOC_DIR(cmd) & _IOC_READ) {
			if (copy_to_user((void *) arg, &em->aspect_ratio, sizeof(em->aspect_ratio)))
				return -EFAULT;
		}
		break;
	case _IOC_NR(EM8300_IOCTL_GET_AUDIOMODE):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			get_user(val, (int *) arg);
			em8300_ioctl_setaudiomode(em, val);
		}
		if (_IOC_DIR(cmd) & _IOC_READ) {
			em8300_ioctl_getaudiomode(em, arg);
		}
		break;
	case _IOC_NR(EM8300_IOCTL_SET_SPUMODE):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			get_user(val, (int *) arg);
			em8300_ioctl_setspumode(em, val);
		}

		if (_IOC_DIR(cmd) & _IOC_READ) {
			if (copy_to_user((void *) arg, &em->sp_mode, sizeof(em->sp_mode)))
				return -EFAULT;
		}
		break;

	case _IOC_NR(EM8300_IOCTL_OVERLAY_SETMODE):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			get_user(val, (int *) arg);
			if (!em8300_ioctl_overlay_setmode(em, val)) {
				return -EINVAL;
			}
		}
		break;

	case _IOC_NR(EM8300_IOCTL_OVERLAY_SIGNALMODE):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			get_user(val, (int *) arg);
			if (!em9010_overlay_set_signalmode(em, val)) {
				return -EINVAL;
			}
		}
		break;

	case _IOC_NR(EM8300_IOCTL_OVERLAY_SETWINDOW):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			if (copy_from_user(&ov_win, (void *) arg, sizeof(em8300_overlay_window_t)))
				return -EFAULT;
			if (!em8300_ioctl_overlay_setwindow(em, &ov_win)) {
				return -EINVAL;
			}
		}
		if (_IOC_DIR(cmd) & _IOC_READ) {
			if (copy_to_user((void *) arg, &ov_win, sizeof(em8300_overlay_window_t)))
				return -EFAULT;
		}
		break;

	case _IOC_NR(EM8300_IOCTL_OVERLAY_SETSCREEN):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			if (copy_from_user(&ov_scr, (void *) arg, sizeof(em8300_overlay_screen_t)))
				return -EFAULT;
			if (!em8300_ioctl_overlay_setscreen(em, &ov_scr)) {
				return -EINVAL;
			}
		}
		if (_IOC_DIR(cmd) & _IOC_READ) {
			if (copy_to_user((void *) arg, &ov_scr, sizeof(em8300_overlay_screen_t)))
				return -EFAULT;
		}
	break;

	case _IOC_NR(EM8300_IOCTL_OVERLAY_CALIBRATE):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			if (copy_from_user(&ov_cal, (void *) arg, sizeof(em8300_overlay_calibrate_t)))
				return -EFAULT;
			if(!em8300_ioctl_overlay_calibrate(em, &ov_cal)) {
				return -EIO;
			}
		}

		if (_IOC_DIR(cmd) & _IOC_READ) {
			if (copy_to_user((void *) arg, &ov_cal, sizeof(em8300_overlay_calibrate_t)))
				return -EFAULT;
		}
	break;

	case _IOC_NR(EM8300_IOCTL_OVERLAY_GET_ATTRIBUTE):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (copy_from_user(&attr, (void *) arg, sizeof(em8300_attribute_t)))
			return -EFAULT;
		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			em9010_set_attribute(em, attr.attribute, attr.value);
		}
		if (_IOC_DIR(cmd) & _IOC_READ) {
			attr.value = em9010_get_attribute(em, attr.attribute);
			if (copy_to_user((void *) arg, &attr, sizeof(em8300_attribute_t)))
				return -EFAULT;
		}
		break;

	case _IOC_NR(EM8300_IOCTL_SCR_GET):
		em8300_require_ucode(em);

		if (!em->ucodeloaded) {
			return -ENOTTY;
		}

		if (_IOC_DIR(cmd) & _IOC_WRITE) {
			unsigned scr;
			if (get_user(val, (unsigned *) arg))
				return -EFAULT;
			scr = read_ucregister(MV_SCRlo) | (read_ucregister(MV_SCRhi) << 16);

			if (scr > val)
				scr = scr - val;
			else
				scr = val - scr;

			if (scr > 2 * 1800) { /* Tolerance: 2 frames */
				pr_info("em8300-%d: adjusting scr: %i\n", em->card_nr, val);
				write_ucregister(MV_SCRlo, val & 0xffff);
				write_ucregister(MV_SCRhi, (val >> 16) & 0xffff);
			}
		}