summaryrefslogtreecommitdiffstats
path: root/linux-2.6-v4l-dvb-update.patch
diff options
context:
space:
mode:
authorJesse Keating <jkeating@redhat.com>2010-07-29 17:18:45 -0700
committerJesse Keating <jkeating@redhat.com>2010-07-29 17:18:45 -0700
commit2f82dda4a9bf41e64e864889bf06564bdf826e25 (patch)
tree118a7b483ae5de4dbf83d20001302f1404866ef0 /linux-2.6-v4l-dvb-update.patch
parent64ba2e5ffde5f2418eb26c700cb0ab62b04e5013 (diff)
downloaddom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.tar.gz
dom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.tar.xz
dom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.zip
initial srpm import
Diffstat (limited to 'linux-2.6-v4l-dvb-update.patch')
-rw-r--r--linux-2.6-v4l-dvb-update.patch366
1 files changed, 366 insertions, 0 deletions
diff --git a/linux-2.6-v4l-dvb-update.patch b/linux-2.6-v4l-dvb-update.patch
new file mode 100644
index 0000000..814bff1
--- /dev/null
+++ b/linux-2.6-v4l-dvb-update.patch
@@ -0,0 +1,366 @@
+Mauro Carvalho Chehab (1):
+ Merge branch 'next' of ../devel into Fedora
+
+Uri Shkolnik (1):
+ V4L/DVB (11241): Siano: SDIO interface driver - remove two redundant lines
+
+diff --git a/linux/drivers/media/dvb/siano/smssdio.c b/linux/drivers/media/dvb/siano/smssdio.c
+new file mode 100644
+index 0000000..4f8fa59
+--- /dev/null
++++ b/linux/drivers/media/dvb/siano/smssdio.c
+@@ -0,0 +1,354 @@
++/*
++ * smssdio.c - Siano 1xxx SDIO interface driver
++ *
++ * Copyright 2008 Pierre Ossman
++ *
++ * Based on code by Siano Mobile Silicon, Inc.,
++ * Copyright (C) 2006-2008, Uri Shkolnik
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at
++ * your option) any later version.
++ *
++ *
++ * This hardware is a bit odd in that all transfers should be done
++ * to/from the SMSSDIO_DATA register, yet the "increase address" bit
++ * always needs to be set.
++ *
++ * Also, buffers from the card are always aligned to 128 byte
++ * boundaries.
++ */
++
++/*
++ * General cleanup notes:
++ *
++ * - only typedefs should be name *_t
++ *
++ * - use ERR_PTR and friends for smscore_register_device()
++ *
++ * - smscore_getbuffer should zero fields
++ *
++ * Fix stop command
++ */
++
++#include <linux/moduleparam.h>
++#include <linux/firmware.h>
++#include <linux/delay.h>
++#include <linux/mmc/card.h>
++#include <linux/mmc/sdio_func.h>
++#include <linux/mmc/sdio_ids.h>
++
++#include "smscoreapi.h"
++#include "sms-cards.h"
++
++/* Registers */
++
++#define SMSSDIO_DATA 0x00
++#define SMSSDIO_INT 0x04
++
++static const struct sdio_device_id smssdio_ids[] = {
++ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
++ .driver_data = SMS1XXX_BOARD_SIANO_STELLAR},
++ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0),
++ .driver_data = SMS1XXX_BOARD_SIANO_NOVA_A},
++ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_B0),
++ .driver_data = SMS1XXX_BOARD_SIANO_NOVA_B},
++ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VEGA_A0),
++ .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
++ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE),
++ .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
++ { /* end: all zeroes */ },
++};
++
++MODULE_DEVICE_TABLE(sdio, smssdio_ids);
++
++struct smssdio_device {
++ struct sdio_func *func;
++
++ struct smscore_device_t *coredev;
++
++ struct smscore_buffer_t *split_cb;
++};
++
++/*******************************************************************/
++/* Siano core callbacks */
++/*******************************************************************/
++
++static int smssdio_sendrequest(void *context, void *buffer, size_t size)
++{
++ int ret;
++ struct smssdio_device *smsdev;
++
++ smsdev = context;
++
++ sdio_claim_host(smsdev->func);
++
++ while (size >= smsdev->func->cur_blksize) {
++ ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1);
++ if (ret)
++ goto out;
++
++ buffer += smsdev->func->cur_blksize;
++ size -= smsdev->func->cur_blksize;
++ }
++
++ if (size) {
++ ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA,
++ buffer, size);
++ }
++
++out:
++ sdio_release_host(smsdev->func);
++
++ return ret;
++}
++
++/*******************************************************************/
++/* SDIO callbacks */
++/*******************************************************************/
++
++static void smssdio_interrupt(struct sdio_func *func)
++{
++ int ret, isr;
++
++ struct smssdio_device *smsdev;
++ struct smscore_buffer_t *cb;
++ struct SmsMsgHdr_ST *hdr;
++ size_t size;
++
++ smsdev = sdio_get_drvdata(func);
++
++ /*
++ * The interrupt register has no defined meaning. It is just
++ * a way of turning of the level triggered interrupt.
++ */
++ isr = sdio_readb(func, SMSSDIO_INT, &ret);
++ if (ret) {
++ dev_err(&smsdev->func->dev,
++ "Unable to read interrupt register!\n");
++ return;
++ }
++
++ if (smsdev->split_cb == NULL) {
++ cb = smscore_getbuffer(smsdev->coredev);
++ if (!cb) {
++ dev_err(&smsdev->func->dev,
++ "Unable to allocate data buffer!\n");
++ return;
++ }
++
++ ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1);
++ if (ret) {
++ dev_err(&smsdev->func->dev,
++ "Error %d reading initial block!\n", ret);
++ return;
++ }
++
++ hdr = cb->p;
++
++ if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) {
++ smsdev->split_cb = cb;
++ return;
++ }
++
++ size = hdr->msgLength - smsdev->func->cur_blksize;
++ } else {
++ cb = smsdev->split_cb;
++ hdr = cb->p;
++
++ size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST);
++
++ smsdev->split_cb = NULL;
++ }
++
++ if (hdr->msgLength > smsdev->func->cur_blksize) {
++ void *buffer;
++
++ size = ALIGN(size, 128);
++ buffer = cb->p + hdr->msgLength;
++
++ BUG_ON(smsdev->func->cur_blksize != 128);
++
++ /*
++ * First attempt to transfer all of it in one go...
++ */
++ ret = sdio_read_blocks(smsdev->func, buffer,
++ SMSSDIO_DATA, size / 128);
++ if (ret && ret != -EINVAL) {
++ smscore_putbuffer(smsdev->coredev, cb);
++ dev_err(&smsdev->func->dev,
++ "Error %d reading data from card!\n", ret);
++ return;
++ }
++
++ /*
++ * ..then fall back to one block at a time if that is
++ * not possible...
++ *
++ * (we have to do this manually because of the
++ * problem with the "increase address" bit)
++ */
++ if (ret == -EINVAL) {
++ while (size) {
++ ret = sdio_read_blocks(smsdev->func,
++ buffer, SMSSDIO_DATA, 1);
++ if (ret) {
++ smscore_putbuffer(smsdev->coredev, cb);
++ dev_err(&smsdev->func->dev,
++ "Error %d reading "
++ "data from card!\n", ret);
++ return;
++ }
++
++ buffer += smsdev->func->cur_blksize;
++ if (size > smsdev->func->cur_blksize)
++ size -= smsdev->func->cur_blksize;
++ else
++ size = 0;
++ }
++ }
++ }
++
++ cb->size = hdr->msgLength;
++ cb->offset = 0;
++
++ smscore_onresponse(smsdev->coredev, cb);
++}
++
++static int smssdio_probe(struct sdio_func *func,
++ const struct sdio_device_id *id)
++{
++ int ret;
++
++ int board_id;
++ struct smssdio_device *smsdev;
++ struct smsdevice_params_t params;
++
++ board_id = id->driver_data;
++
++ smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL);
++ if (!smsdev)
++ return -ENOMEM;
++
++ smsdev->func = func;
++
++ memset(&params, 0, sizeof(struct smsdevice_params_t));
++
++ params.device = &func->dev;
++ params.buffer_size = 0x5000; /* ?? */
++ params.num_buffers = 22; /* ?? */
++ params.context = smsdev;
++
++ snprintf(params.devpath, sizeof(params.devpath),
++ "sdio\\%s", sdio_func_id(func));
++
++ params.sendrequest_handler = smssdio_sendrequest;
++
++ params.device_type = sms_get_board(board_id)->type;
++
++ if (params.device_type != SMS_STELLAR)
++ params.flags |= SMS_DEVICE_FAMILY2;
++ else {
++ /*
++ * FIXME: Stellar needs special handling...
++ */
++ ret = -ENODEV;
++ goto free;
++ }
++
++ ret = smscore_register_device(&params, &smsdev->coredev);
++ if (ret < 0)
++ goto free;
++
++ smscore_set_board_id(smsdev->coredev, board_id);
++
++ sdio_claim_host(func);
++
++ ret = sdio_enable_func(func);
++ if (ret)
++ goto release;
++
++ ret = sdio_set_block_size(func, 128);
++ if (ret)
++ goto disable;
++
++ ret = sdio_claim_irq(func, smssdio_interrupt);
++ if (ret)
++ goto disable;
++
++ sdio_set_drvdata(func, smsdev);
++
++ sdio_release_host(func);
++
++ ret = smscore_start_device(smsdev->coredev);
++ if (ret < 0)
++ goto reclaim;
++
++ return 0;
++
++reclaim:
++ sdio_claim_host(func);
++ sdio_release_irq(func);
++disable:
++ sdio_disable_func(func);
++release:
++ sdio_release_host(func);
++ smscore_unregister_device(smsdev->coredev);
++free:
++ kfree(smsdev);
++
++ return ret;
++}
++
++static void smssdio_remove(struct sdio_func *func)
++{
++ struct smssdio_device *smsdev;
++
++ smsdev = sdio_get_drvdata(func);
++
++ /* FIXME: racy! */
++ if (smsdev->split_cb)
++ smscore_putbuffer(smsdev->coredev, smsdev->split_cb);
++
++ smscore_unregister_device(smsdev->coredev);
++
++ sdio_claim_host(func);
++ sdio_release_irq(func);
++ sdio_disable_func(func);
++ sdio_release_host(func);
++
++ kfree(smsdev);
++}
++
++static struct sdio_driver smssdio_driver = {
++ .name = "smssdio",
++ .id_table = smssdio_ids,
++ .probe = smssdio_probe,
++ .remove = smssdio_remove,
++};
++
++/*******************************************************************/
++/* Module functions */
++/*******************************************************************/
++
++int smssdio_register(void)
++{
++ int ret = 0;
++
++ printk(KERN_INFO "smssdio: Siano SMS1xxx SDIO driver\n");
++ printk(KERN_INFO "smssdio: Copyright Pierre Ossman\n");
++
++ ret = sdio_register_driver(&smssdio_driver);
++
++ return ret;
++}
++
++void smssdio_unregister(void)
++{
++ sdio_unregister_driver(&smssdio_driver);
++}
++
++MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver");
++MODULE_AUTHOR("Pierre Ossman");
++MODULE_LICENSE("GPL");