Ejemplo n.º 1
0
static void sa1100_irda_shutdown(struct sa1100_irda *si)
{
	/*
	 * Stop all DMA activity.
	 */
	sa1100_dma_stop(si->rxdma);
	sa1100_dma_stop(si->txdma);

	/* Disable the port. */
	Ser2UTCR3 = 0;
	Ser2HSCR0 = 0;
}
Ejemplo n.º 2
0
/*
 * FIR format interrupt service routine.  We only have to
 * handle RX events; transmit events go via the TX DMA handler.
 *
 * No matter what, we disable RX, process, and the restart RX.
 */
static void sa1100_irda_fir_irq(struct net_device *dev)
{
	struct sa1100_irda *si = dev->priv;

	/*
	 * Stop RX DMA
	 */
	sa1100_dma_stop(si->rxdma);

	/*
	 * Framing error - we throw away the packet completely.
	 * Clearing RXE flushes the error conditions and data
	 * from the fifo.
	 */
	if (Ser2HSSR0 & (HSSR0_FRE | HSSR0_RAB)) {
		si->stats.rx_errors++;

		if (Ser2HSSR0 & HSSR0_FRE)
			si->stats.rx_frame_errors++;

		/*
		 * Clear out the DMA...
		 */
		Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;

		/*
		 * Clear selected status bits now, so we
		 * don't miss them next time around.
		 */
		Ser2HSSR0 = HSSR0_FRE | HSSR0_RAB;
	}

	/*
	 * Deal with any receive errors.  The any of the lowest
	 * 8 bytes in the FIFO may contain an error.  We must read
	 * them one by one.  The "error" could even be the end of
	 * packet!
	 */
	if (Ser2HSSR0 & HSSR0_EIF)
		sa1100_irda_fir_error(si, dev);

	/*
	 * No matter what happens, we must restart reception.
	 */
	sa1100_irda_rx_dma_start(si);
}
Ejemplo n.º 3
0
static int audio_ioctl(struct inode *inode, struct file *file,
		       uint cmd, ulong arg)
{
	audio_state_t *state = (audio_state_t *)file->private_data;
	audio_stream_t *os = state->output_stream;
	audio_stream_t *is = state->input_stream;
	long val;

	/* dispatch based on command */
	switch (cmd) {
	case OSS_GETVERSION:
		return put_user(SOUND_VERSION, (int *)arg);

	case SNDCTL_DSP_GETBLKSIZE:
		if (file->f_mode & FMODE_WRITE)
			return put_user(os->fragsize, (int *)arg);
		else
			return put_user(is->fragsize, (int *)arg);

	case SNDCTL_DSP_GETCAPS:
		val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;
		if (is && os)
			val |= DSP_CAP_DUPLEX;
		return put_user(val, (int *)arg);

	case SNDCTL_DSP_SETFRAGMENT:
		if (get_user(val, (long *) arg))
			return -EFAULT;
		if (file->f_mode & FMODE_READ) {
			int ret = audio_set_fragments(is, val);
			if (ret < 0)
				return ret;
			ret = put_user(ret, (int *)arg);
			if (ret)
				return ret;
		}
		if (file->f_mode & FMODE_WRITE) {
			int ret = audio_set_fragments(os, val);
			if (ret < 0)
				return ret;
			ret = put_user(ret, (int *)arg);
			if (ret)
				return ret;
		}
		return 0;

	case SNDCTL_DSP_SYNC:
		return audio_sync(file);

	case SNDCTL_DSP_SETDUPLEX:
		return 0;

	case SNDCTL_DSP_POST:
		return 0;

	case SNDCTL_DSP_GETTRIGGER:
		val = 0;
		if (file->f_mode & FMODE_READ && is->active && !is->stopped)
			val |= PCM_ENABLE_INPUT;
		if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
			val |= PCM_ENABLE_OUTPUT;
		return put_user(val, (int *)arg);

	case SNDCTL_DSP_SETTRIGGER:
		if (get_user(val, (int *)arg))
			return -EFAULT;
		if (file->f_mode & FMODE_READ) {
			if (val & PCM_ENABLE_INPUT) {
				if (!is->active) {
					if (!is->buffers && audio_setup_buf(is))
						return -ENOMEM;
					audio_prime_dma(is);
				}
				audio_check_tx_spin(state);
				if (is->stopped) {
					is->stopped = 0;
					sa1100_dma_resume(is->dma_ch);
				}
			} else {
				sa1100_dma_stop(is->dma_ch);
				is->stopped = 1;
			}
		}
		if (file->f_mode & FMODE_WRITE) {
			if (val & PCM_ENABLE_OUTPUT) {
				if (!os->active) {
					if (!os->buffers && audio_setup_buf(os))
						return -ENOMEM;
					if (os->mapped)
						audio_prime_dma(os);
				}
				if (os->stopped) {
					os->stopped = 0;
					sa1100_dma_resume(os->dma_ch);
				}
			} else {
				sa1100_dma_stop(os->dma_ch);
				os->stopped = 1;
			}
		}
		return 0;

	case SNDCTL_DSP_GETOPTR:
	case SNDCTL_DSP_GETIPTR:
	    {
		count_info inf = { 0, };
		audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
		audio_buf_t *b;
		dma_addr_t ptr;
		int bytecount, offset, flags;

		if ((s == is && !(file->f_mode & FMODE_READ)) ||
		    (s == os && !(file->f_mode & FMODE_WRITE)))
			return -EINVAL;
		if (s->active) {
			save_flags_cli(flags);
			if (sa1100_dma_get_current(s->dma_ch, (void *)&b, &ptr) == 0) {
				offset = ptr - b->dma_addr;
				inf.ptr = (b - s->buffers) * s->fragsize + offset;
			} else offset = 0;
			bytecount = s->bytecount + offset;
			s->bytecount = -offset;
			inf.blocks = s->fragcount;
			s->fragcount = 0;
			restore_flags(flags);
			if (bytecount < 0)
				bytecount = 0;
			inf.bytes = bytecount;
		}
		return copy_to_user((void *)arg, &inf, sizeof(inf));
	    }

	case SNDCTL_DSP_GETOSPACE:
	    {
		audio_buf_info inf = { 0, };
		int i;

		if (!(file->f_mode & FMODE_WRITE))
			return -EINVAL;
		if (!os->buffers && audio_setup_buf(os))
			return -ENOMEM;
		for (i = 0; i < os->nbfrags; i++) {
			if (atomic_read(&os->buffers[i].sem.count) > 0) {
				if (os->buffers[i].size == 0)
					inf.fragments++;
				inf.bytes += os->fragsize - os->buffers[i].size;
			}
		}
		inf.fragstotal = os->nbfrags;
		inf.fragsize = os->fragsize;
		return copy_to_user((void *)arg, &inf, sizeof(inf));
	    }

	case SNDCTL_DSP_GETISPACE:
	    {
		audio_buf_info inf = { 0, };
		int i;

		if (!(file->f_mode & FMODE_READ))
			return -EINVAL;
		if (!is->buffers && audio_setup_buf(is))
			return -ENOMEM;
		for (i = 0; i < is->nbfrags; i++) {
			if (atomic_read(&is->buffers[i].sem.count) > 0) {
				if (is->buffers[i].size == is->fragsize)
					inf.fragments++;
				inf.bytes += is->buffers[i].size;
			}
		}
		inf.fragstotal = is->nbfrags;
		inf.fragsize = is->fragsize;
		return copy_to_user((void *)arg, &inf, sizeof(inf));
	    }

	case SNDCTL_DSP_NONBLOCK:
		file->f_flags |= O_NONBLOCK;
		return 0;

        case SNDCTL_DSP_GETODELAY: {
                int count = 0;
                int i;
		int flags;
		audio_buf_t *b;
		dma_addr_t ptr;
		if (!(file->f_mode & FMODE_WRITE))
			return -EINVAL;
		if (!os->buffers && audio_setup_buf(os))
			return -ENOMEM;
		save_flags_cli(flags);
		for (i = 0; i < os->nbfrags; i++) {
                        /* if contains data */
			if (atomic_read(&os->buffers[i].sem.count) <= 0) {
				count += os->fragsize;
			}
		}
		if (sa1100_dma_get_current(os->dma_ch, (void *)&b, &ptr) == 0)
			count -= ptr - b->dma_addr;
		restore_flags(flags);
                return put_user(count, (int *)arg);
        }

	case SNDCTL_DSP_RESET:
		if (file->f_mode & FMODE_READ) {
			if (state->tx_spinning) {
				sa1100_dma_set_spin(os->dma_ch, 0, 0);
				state->tx_spinning = 0;
			}
			audio_reset_buf(is);
		}
		if (file->f_mode & FMODE_WRITE) {
			audio_reset_buf(os);
		}
		return 0;

	default:
		/*
		 * Let the client of this module handle the
		 * non generic ioctls
		 */
		return state->client_ioctl(inode, file, cmd, arg);
	}

	return 0;
}
Ejemplo n.º 4
0
/*
 * Set the IrDA communications speed.
 */
static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed)
{
	unsigned long flags;
	int brd, ret = -EINVAL;

	switch (speed) {
	case 9600:	case 19200:	case 38400:
	case 57600:	case 115200:
		brd = 3686400 / (16 * speed) - 1;

		/*
		 * Stop the receive DMA.
		 */
		if (IS_FIR(si))
			sa1100_dma_stop(si->rxdma);

		local_irq_save(flags);

		Ser2UTCR3 = 0;
		Ser2HSCR0 = HSCR0_UART;

		Ser2UTCR1 = brd >> 8;
		Ser2UTCR2 = brd;

		/*
		 * Clear status register
		 */
		Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
		Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;

		if (machine_is_assabet())
			ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL);
		if (machine_is_h3600())
			clr_h3600_egpio(EGPIO_H3600_IR_FSEL);
		if (machine_is_yopy())
			PPSR &= ~GPIO_IRDA_FIR;

		si->speed = speed;

		local_irq_restore(flags);
		ret = 0;
		break;

	case 4000000:
		save_flags(flags);
		cli();

		si->hscr0 = 0;

		Ser2HSSR0 = 0xff;
		Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;
		Ser2UTCR3 = 0;

		si->speed = speed;

		if (machine_is_assabet())
			ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL);
		if (machine_is_h3600())
			set_h3600_egpio(EGPIO_H3600_IR_FSEL);
		if (machine_is_yopy())
			PPSR |= GPIO_IRDA_FIR;

		sa1100_irda_rx_alloc(si);
		sa1100_irda_rx_dma_start(si);

		restore_flags(flags);

		break;

	default:
		break;
	}

	return ret;
}