From 70c66567d1e41d8b2186a2d198997a1c8d79c0c4 Mon Sep 17 00:00:00 2001 From: Petr Štetiar Date: Wed, 9 Dec 2009 22:09:53 +0100 Subject: HID: blacklist ET&T TC5UH touchscreen controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds ET&T TC5UH touchscreen controller to HID blacklist, because this device is handled by input/usbtouchscreen driver. Signed-off-by: Petr Štetiar Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 80792d38d25..389cd5f0a68 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1553,6 +1553,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 3839340e293..b9de32b6b10 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -166,6 +166,9 @@ #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 +#define USB_VENDOR_ID_ETT 0x0664 +#define USB_DEVICE_ID_TC5UH 0x0309 + #define USB_VENDOR_ID_EZKEY 0x0518 #define USB_DEVICE_ID_BTC_8193 0x0002 -- cgit v1.2.3-70-g09d2 From 3975bc56305256af7689bcce62284fc62e09fc8f Mon Sep 17 00:00:00 2001 From: Robert Schedel Date: Fri, 11 Dec 2009 00:37:11 +0100 Subject: HID: Support 171 byte variant of Samsung USB IR receiver Extends the existing Samsung USB IrDA (0419:0001) quirk with newly reported 171 byte variant. It needs the same quirk as the other devices already supported by hid-samsung (wrong logical range) Refactors duplicate trace call into local helper function. The original bug report for the new variant is available at the second half of this ticket page: https://bugs.launchpad.net/bugs/326986 Signed-off-by: Robert Schedel Signed-off-by: Jiri Kosina --- drivers/hid/hid-samsung.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c index 5b222eed069..510dd134059 100644 --- a/drivers/hid/hid-samsung.c +++ b/drivers/hid/hid-samsung.c @@ -39,7 +39,17 @@ * * 3. 135 byte report descriptor * Report #4 has an array field with logical range 0..17 instead of 1..14. + * + * 4. 171 byte report descriptor + * Report #3 has an array field with logical range 0..1 instead of 1..3. */ +static inline void samsung_dev_trace(struct hid_device *hdev, + unsigned int rsize) +{ + dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " + "descriptor\n", rsize); +} + static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int rsize) { @@ -47,8 +57,7 @@ static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[177] == 0x75 && rdesc[178] == 0x30 && rdesc[179] == 0x95 && rdesc[180] == 0x01 && rdesc[182] == 0x40) { - dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " - "descriptor\n", 184); + samsung_dev_trace(hdev, 184); rdesc[176] = 0xff; rdesc[178] = 0x08; rdesc[180] = 0x06; @@ -56,17 +65,21 @@ static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, } else if (rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 && rdesc[194] == 0x25 && rdesc[195] == 0x12) { - dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " - "descriptor\n", 203); + samsung_dev_trace(hdev, 203); rdesc[193] = 0x1; rdesc[195] = 0xf; } else if (rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 && rdesc[126] == 0x25 && rdesc[127] == 0x11) { - dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " - "descriptor\n", 135); + samsung_dev_trace(hdev, 135); rdesc[125] = 0x1; rdesc[127] = 0xe; + } else + if (rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 && + rdesc[162] == 0x25 && rdesc[163] == 0x01) { + samsung_dev_trace(hdev, 171); + rdesc[161] = 0x1; + rdesc[163] = 0x3; } } -- cgit v1.2.3-70-g09d2 From a62e8f1978f49e52f87a711ff6711b323d4b12ff Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Thu, 24 Dec 2009 11:34:16 +0300 Subject: ACPI: EC: Accelerate query execution Split EC query handling into acknowledge and execution phase. This allows much smaller pending query lattency and lowers chances of EC going "wild" and losing events. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14858 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 122 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index fd1801bdee6..9cc38857c33 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -201,14 +201,13 @@ unlock: spin_unlock_irqrestore(&ec->curr_lock, flags); } -static void acpi_ec_gpe_query(void *ec_cxt); +static int acpi_ec_sync_query(struct acpi_ec *ec); -static int ec_check_sci(struct acpi_ec *ec, u8 state) +static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) { if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) - return acpi_os_execute(OSL_EC_BURST_HANDLER, - acpi_ec_gpe_query, ec); + return acpi_ec_sync_query(ec); } return 0; } @@ -249,11 +248,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, { unsigned long tmp; int ret = 0; - pr_debug(PREFIX "transaction start\n"); - /* disable GPE during transaction if storm is detected */ - if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { - acpi_disable_gpe(NULL, ec->gpe); - } if (EC_FLAGS_MSI) udelay(ACPI_EC_MSI_UDELAY); /* start transaction */ @@ -269,16 +263,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, spin_lock_irqsave(&ec->curr_lock, tmp); ec->curr = NULL; spin_unlock_irqrestore(&ec->curr_lock, tmp); - if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { - /* check if we received SCI during transaction */ - ec_check_sci(ec, acpi_ec_read_status(ec)); - /* it is safe to enable GPE outside of transaction */ - acpi_enable_gpe(NULL, ec->gpe); - } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { - pr_info(PREFIX "GPE storm detected, " - "transactions will use polling mode\n"); - set_bit(EC_FLAGS_GPE_STORM, &ec->flags); - } return ret; } @@ -321,7 +305,24 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) status = -ETIME; goto end; } + pr_debug(PREFIX "transaction start\n"); + /* disable GPE during transaction if storm is detected */ + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + acpi_disable_gpe(NULL, ec->gpe); + } + status = acpi_ec_transaction_unlocked(ec, t); + + /* check if we received SCI during transaction */ + ec_check_sci_sync(ec, acpi_ec_read_status(ec)); + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + /* it is safe to enable GPE outside of transaction */ + acpi_enable_gpe(NULL, ec->gpe); + } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { + pr_info(PREFIX "GPE storm detected, " + "transactions will use polling mode\n"); + set_bit(EC_FLAGS_GPE_STORM, &ec->flags); + } end: if (ec->global_lock) acpi_release_global_lock(glk); @@ -443,7 +444,7 @@ int ec_transaction(u8 command, EXPORT_SYMBOL(ec_transaction); -static int acpi_ec_query(struct acpi_ec *ec, u8 * data) +static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) { int result; u8 d; @@ -452,20 +453,16 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) .wlen = 0, .rlen = 1}; if (!ec || !data) return -EINVAL; - /* * Query the EC to find out which _Qxx method we need to evaluate. * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source). */ - - result = acpi_ec_transaction(ec, &t); + result = acpi_ec_transaction_unlocked(ec, &t); if (result) return result; - if (!d) return -ENODATA; - *data = d; return 0; } @@ -509,43 +506,78 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); -static void acpi_ec_gpe_query(void *ec_cxt) +static void acpi_ec_run(void *cxt) { - struct acpi_ec *ec = ec_cxt; - u8 value = 0; - struct acpi_ec_query_handler *handler, copy; - - if (!ec || acpi_ec_query(ec, &value)) + struct acpi_ec_query_handler *handler = cxt; + if (!handler) return; - mutex_lock(&ec->lock); + pr_debug(PREFIX "start query execution\n"); + if (handler->func) + handler->func(handler->data); + else if (handler->handle) + acpi_evaluate_object(handler->handle, NULL, NULL, NULL); + pr_debug(PREFIX "stop query execution\n"); + kfree(handler); +} + +static int acpi_ec_sync_query(struct acpi_ec *ec) +{ + u8 value = 0; + int status; + struct acpi_ec_query_handler *handler, *copy; + if ((status = acpi_ec_query_unlocked(ec, &value))) + return status; list_for_each_entry(handler, &ec->list, node) { if (value == handler->query_bit) { /* have custom handler for this bit */ - memcpy(©, handler, sizeof(copy)); - mutex_unlock(&ec->lock); - if (copy.func) { - copy.func(copy.data); - } else if (copy.handle) { - acpi_evaluate_object(copy.handle, NULL, NULL, NULL); - } - return; + copy = kmalloc(sizeof(*handler), GFP_KERNEL); + if (!copy) + return -ENOMEM; + memcpy(copy, handler, sizeof(*copy)); + pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); + return acpi_os_execute(OSL_GPE_HANDLER, + acpi_ec_run, copy); } } + return 0; +} + +static void acpi_ec_gpe_query(void *ec_cxt) +{ + struct acpi_ec *ec = ec_cxt; + if (!ec) + return; + mutex_lock(&ec->lock); + acpi_ec_sync_query(ec); mutex_unlock(&ec->lock); } +static void acpi_ec_gpe_query(void *ec_cxt); + +static int ec_check_sci(struct acpi_ec *ec, u8 state) +{ + if (state & ACPI_EC_FLAG_SCI) { + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { + pr_debug(PREFIX "push gpe query to the queue\n"); + return acpi_os_execute(OSL_NOTIFY_HANDLER, + acpi_ec_gpe_query, ec); + } + } + return 0; +} + static u32 acpi_ec_gpe_handler(void *data) { struct acpi_ec *ec = data; - u8 status; pr_debug(PREFIX "~~~> interrupt\n"); - status = acpi_ec_read_status(ec); - advance_transaction(ec, status); - if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) + advance_transaction(ec, acpi_ec_read_status(ec)); + if (ec_transaction_done(ec) && + (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { wake_up(&ec->wait); - ec_check_sci(ec, status); + ec_check_sci(ec, acpi_ec_read_status(ec)); + } return ACPI_INTERRUPT_HANDLED; } -- cgit v1.2.3-70-g09d2 From 0798219f6154baa6a8efe767bfffb4a724e4b1e1 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 28 Dec 2009 16:58:38 +0100 Subject: drbd: Use drbd_crypto_is_hash() instead of an open coded check Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 4e0726aa53b..3313901a486 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1271,7 +1271,7 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, goto fail; } - if (crypto_tfm_alg_type(crypto_hash_tfm(tfm)) != CRYPTO_ALG_TYPE_SHASH) { + if (!drbd_crypto_is_hash(crypto_hash_tfm(tfm))) { retcode = ERR_AUTH_ALG_ND; goto fail; } -- cgit v1.2.3-70-g09d2 From 0a6dbf2bc4ea3781c530f895e2d92fd3c4a735a2 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 28 Dec 2009 16:58:38 +0100 Subject: drbd: Fix for a race between IO and a detach operation [Bugz 262] In D_DISKLESS we do not hand out any new references to ldev (local_cnt) therefore waiting until all previously handed out refereces got returned is sufficient before actually freeing mdev->ldev. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 9348f33f624..e898ad9eb1c 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1298,6 +1298,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, dev_err(DEV, "Sending state in drbd_io_error() failed\n"); } + wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt)); lc_destroy(mdev->resync); mdev->resync = NULL; lc_destroy(mdev->act_log); -- cgit v1.2.3-70-g09d2 From 89f01d5cd3c7ef01239bf15283181a0091c78657 Mon Sep 17 00:00:00 2001 From: Johannes Thoma Date: Tue, 29 Dec 2009 16:38:04 +0100 Subject: drbd: Kconfig fix !CONFIG_OPT evalues to FALSE if CONFIG_OPT='m'. Do not display the "DRBD disabled..." message if the dependencies are compiled as module. Signed-off-by: Johannes Thoma Signed-off-by: Philipp Reisner --- drivers/block/drbd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/Kconfig b/drivers/block/drbd/Kconfig index f4acd04ebee..df098378739 100644 --- a/drivers/block/drbd/Kconfig +++ b/drivers/block/drbd/Kconfig @@ -3,7 +3,7 @@ # comment "DRBD disabled because PROC_FS, INET or CONNECTOR not selected" - depends on !PROC_FS || !INET || !CONNECTOR + depends on PROC_FS='n' || INET='n' || CONNECTOR='n' config BLK_DEV_DRBD tristate "DRBD Distributed Replicated Block Device support" -- cgit v1.2.3-70-g09d2 From 3b8cb427e9281790f36e847e46cb1d005a50cec0 Mon Sep 17 00:00:00 2001 From: Chen Gong Date: Mon, 14 Dec 2009 09:42:28 +0800 Subject: acpi_pad: fix error checks There are some fixes listed below: 1. When met a bogus BIOS, the return value of cpu number maybe is a negative value so that acpi_pad_pur get an unexpected result. 2. the return value of function acpi_pad_idle_cpus is useless. 3. enhance the process of create_power_saving_task/destroy_power_saving_task 4. Add more error checks when evaluating _PUR object. 5. one typo fix Signed-off-by: Chen Gong Acked-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/acpi_pad.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 0d2cdb86158..a7bd49f0f01 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -207,7 +207,7 @@ static int power_saving_thread(void *data) * the mechanism only works when all CPUs have RT task running, * as if one CPU hasn't RT task, RT task from other CPUs will * borrow CPU time from this CPU and cause RT task use > 95% - * CPU time. To make 'avoid staration' work, takes a nap here. + * CPU time. To make 'avoid starvation' work, takes a nap here. */ if (do_sleep) schedule_timeout_killable(HZ * idle_pct / 100); @@ -221,14 +221,18 @@ static struct task_struct *ps_tsks[NR_CPUS]; static unsigned int ps_tsk_num; static int create_power_saving_task(void) { + int rc = -ENOMEM; + ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, (void *)(unsigned long)ps_tsk_num, "power_saving/%d", ps_tsk_num); - if (ps_tsks[ps_tsk_num]) { + rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0; + if (!rc) ps_tsk_num++; - return 0; - } - return -EINVAL; + else + ps_tsks[ps_tsk_num] = NULL; + + return rc; } static void destroy_power_saving_task(void) @@ -236,6 +240,7 @@ static void destroy_power_saving_task(void) if (ps_tsk_num > 0) { ps_tsk_num--; kthread_stop(ps_tsks[ps_tsk_num]); + ps_tsks[ps_tsk_num] = NULL; } } @@ -252,7 +257,7 @@ static void set_power_saving_task_num(unsigned int num) } } -static int acpi_pad_idle_cpus(unsigned int num_cpus) +static void acpi_pad_idle_cpus(unsigned int num_cpus) { get_online_cpus(); @@ -260,7 +265,6 @@ static int acpi_pad_idle_cpus(unsigned int num_cpus) set_power_saving_task_num(num_cpus); put_online_cpus(); - return 0; } static uint32_t acpi_pad_idle_cpus_num(void) @@ -368,19 +372,21 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device) static int acpi_pad_pur(acpi_handle handle, int *num_cpus) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_status status; union acpi_object *package; int rev, num, ret = -EINVAL; - status = acpi_evaluate_object(handle, "_PUR", NULL, &buffer); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer))) + return -EINVAL; + + if (!buffer.length || !buffer.pointer) return -EINVAL; + package = buffer.pointer; if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2) goto out; rev = package->package.elements[0].integer.value; num = package->package.elements[1].integer.value; - if (rev != 1) + if (rev != 1 || num < 0) goto out; *num_cpus = num; ret = 0; @@ -409,7 +415,7 @@ static void acpi_pad_ost(acpi_handle handle, int stat, static void acpi_pad_handle_notify(acpi_handle handle) { - int num_cpus, ret; + int num_cpus; uint32_t idle_cpus; mutex_lock(&isolated_cpus_lock); @@ -417,12 +423,9 @@ static void acpi_pad_handle_notify(acpi_handle handle) mutex_unlock(&isolated_cpus_lock); return; } - ret = acpi_pad_idle_cpus(num_cpus); + acpi_pad_idle_cpus(num_cpus); idle_cpus = acpi_pad_idle_cpus_num(); - if (!ret) - acpi_pad_ost(handle, 0, idle_cpus); - else - acpi_pad_ost(handle, 1, 0); + acpi_pad_ost(handle, 0, idle_cpus); mutex_unlock(&isolated_cpus_lock); } -- cgit v1.2.3-70-g09d2 From c504f8cb68eb0d6cde53ba043daff8cb34586493 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 30 Dec 2009 15:59:23 +0800 Subject: ACPI video: Prune dupe video devices, unless "video.allow_duplicates" Some buggy BIOS exports multiple ACPI video bus devices for the same VGA controller, and multiple backlight control methods as well. This messes up the ACPI video backlight control. http://bugzilla.kernel.org/show_bug.cgi?id=13577 With this patch applied, only the FIRST ACPI video bus device under a PCI device node is bind to ACPI video driver by default. If the first ACPI video bus device doesn't work well, we can use video.allow_duplicates=1 to go back to the old behavior. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 05dff631591..45e6a29c817 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -78,6 +78,13 @@ MODULE_LICENSE("GPL"); static int brightness_switch_enabled = 1; module_param(brightness_switch_enabled, bool, 0644); +/* + * By default, we don't allow duplicate ACPI video bus devices + * under the same VGA controller + */ +static int allow_duplicates; +module_param(allow_duplicates, bool, 0644); + static int register_count = 0; static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device, int type); @@ -2233,11 +2240,47 @@ static int acpi_video_resume(struct acpi_device *device) return AE_OK; } +static acpi_status +acpi_video_bus_match(acpi_handle handle, u32 level, void *context, + void **return_value) +{ + struct acpi_device *device = context; + struct acpi_device *sibling; + int result; + + if (handle == device->handle) + return AE_CTRL_TERMINATE; + + result = acpi_bus_get_device(handle, &sibling); + if (result) + return AE_OK; + + if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME)) + return AE_ALREADY_EXISTS; + + return AE_OK; +} + static int acpi_video_bus_add(struct acpi_device *device) { struct acpi_video_bus *video; struct input_dev *input; int error; + acpi_status status; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, + device->parent->handle, 1, + acpi_video_bus_match, NULL, + device, NULL); + if (status == AE_ALREADY_EXISTS) { + printk(KERN_WARNING FW_BUG + "Duplicate ACPI video bus devices for the" + " same VGA controller, please try module " + "parameter \"video.allow_duplicates=1\"" + "if the current driver doesn't work.\n"); + if (!allow_duplicates) + return -ENODEV; + } video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); if (!video) -- cgit v1.2.3-70-g09d2 From 367a8d738542b091228613751af0958ce25bbeb3 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 29 Dec 2009 15:56:01 +0100 Subject: drbd: Silenced an assert that could triggered after changing write ordering method Immediately after changing the write ordering method, the epoch can already be finished at this point. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 259c1351b15..a6d266ee7e2 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1201,10 +1201,11 @@ static int receive_Barrier(struct drbd_conf *mdev, struct p_header *h) case WO_bdev_flush: case WO_drain_io: - D_ASSERT(rv == FE_STILL_LIVE); - set_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &mdev->current_epoch->flags); - drbd_wait_ee_list_empty(mdev, &mdev->active_ee); - rv = drbd_flush_after_epoch(mdev, mdev->current_epoch); + if (rv == FE_STILL_LIVE) { + set_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &mdev->current_epoch->flags); + drbd_wait_ee_list_empty(mdev, &mdev->active_ee); + rv = drbd_flush_after_epoch(mdev, mdev->current_epoch); + } if (rv == FE_RECYCLED) return TRUE; -- cgit v1.2.3-70-g09d2 From 0f4bd46ec252887f44f1f065b41867cac8f70dfb Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Tue, 22 Dec 2009 03:15:43 +0000 Subject: kmsg_dump: Dump on crash_kexec as well crash_kexec gets called before kmsg_dump(KMSG_DUMP_OOPS) if panic_on_oops is set, so the kernel log buffer is not stored for this case. This patch adds a KMSG_DUMP_KEXEC dump type which gets called when crash_kexec() is invoked. To avoid getting double dumps, the old KMSG_DUMP_PANIC is moved below crash_kexec(). The mtdoops driver is modified to handle KMSG_DUMP_KEXEC in the same way as a panic. Signed-off-by: KOSAKI Motohiro Acked-by: Simon Kagstrom Signed-off-by: David Woodhouse --- drivers/mtd/mtdoops.c | 2 +- include/linux/kmsg_dump.h | 1 + kernel/kexec.c | 4 ++++ kernel/panic.c | 3 ++- kernel/printk.c | 1 + 5 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index a714ec48276..92e12df0917 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c @@ -322,7 +322,7 @@ static void mtdoops_do_dump(struct kmsg_dumper *dumper, memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy); /* Panics must be written immediately */ - if (reason == KMSG_DUMP_PANIC) { + if (reason != KMSG_DUMP_OOPS) { if (!cxt->mtd->panic_write) printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n"); else diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h index e32aa268efa..24b44145a88 100644 --- a/include/linux/kmsg_dump.h +++ b/include/linux/kmsg_dump.h @@ -17,6 +17,7 @@ enum kmsg_dump_reason { KMSG_DUMP_OOPS, KMSG_DUMP_PANIC, + KMSG_DUMP_KEXEC, }; /** diff --git a/kernel/kexec.c b/kernel/kexec.c index 433e9fcc1fc..ae217488fef 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -1074,6 +1075,9 @@ void crash_kexec(struct pt_regs *regs) if (mutex_trylock(&kexec_mutex)) { if (kexec_crash_image) { struct pt_regs fixed_regs; + + kmsg_dump(KMSG_DUMP_KEXEC); + crash_setup_regs(&fixed_regs, regs); crash_save_vmcoreinfo(); machine_crash_shutdown(&fixed_regs); diff --git a/kernel/panic.c b/kernel/panic.c index 5827f7b9725..c787333282b 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -75,7 +75,6 @@ NORET_TYPE void panic(const char * fmt, ...) dump_stack(); #endif - kmsg_dump(KMSG_DUMP_PANIC); /* * If we have crashed and we have a crash kernel loaded let it handle * everything else. @@ -83,6 +82,8 @@ NORET_TYPE void panic(const char * fmt, ...) */ crash_kexec(NULL); + kmsg_dump(KMSG_DUMP_PANIC); + /* * Note smp_send_stop is the usual smp shutdown function, which * unfortunately means it may not be hardened to work in a panic diff --git a/kernel/printk.c b/kernel/printk.c index 1ded8e7dd19..2c9dc0b03a5 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1467,6 +1467,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_unregister); static const char const *kmsg_reasons[] = { [KMSG_DUMP_OOPS] = "oops", [KMSG_DUMP_PANIC] = "panic", + [KMSG_DUMP_KEXEC] = "kexec", }; static const char *kmsg_to_str(enum kmsg_dump_reason reason) -- cgit v1.2.3-70-g09d2 From abf2a117c67a67fbb611913a31109d0ff66ab073 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 1 Jan 2010 18:35:11 -0800 Subject: Input: gf2k - fix &&/|| confusion in gf2k_connect() This always evaluates to true. Signed-off-by: Roel Kluin Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/gf2k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index 67c207f5b1a..45ac70eae0a 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c @@ -277,7 +277,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) } #ifdef RESET_WORKS - if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) || + if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) && (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) { err = -ENODEV; goto fail2; -- cgit v1.2.3-70-g09d2 From 2d1ee87d8763b38668f6f11bb53abb689a49a43e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 27 Dec 2009 22:27:11 +0100 Subject: drivers/block/drbd: Correct NULL test Test the just-allocated value for NULL rather than some other value. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,y; statement S; @@ x = \(kmalloc\|kcalloc\|kzalloc\)(...); ( if ((x) == NULL) S | if ( - y + x == NULL) S ) // Signed-off-by: Julia Lawall Signed-off-by: Philipp Reisner --- drivers/block/drbd/drbd_receiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index a6d266ee7e2..dbd451984e0 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3945,7 +3945,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) } right_response = kmalloc(resp_size, GFP_NOIO); - if (response == NULL) { + if (right_response == NULL) { dev_err(DEV, "kmalloc of right_response failed\n"); rv = 0; goto fail; -- cgit v1.2.3-70-g09d2 From 4ef250114f6672dd36f9b961a71d229642517645 Mon Sep 17 00:00:00 2001 From: Dominik Geyer Date: Tue, 29 Dec 2009 08:27:57 +0100 Subject: ath9k: Fix Kconfig depends for ATH9K_DEBUGFS Add missing DEBUG_FS dependency for ATH9K_DEBUGFS in ath9k's Kconfig. Signed-off-by: Dominik D. Geyer Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 03a1106ad72..5774cea23a3 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -25,7 +25,7 @@ config ATH9K config ATH9K_DEBUGFS bool "Atheros ath9k debugging" - depends on ATH9K + depends on ATH9K && DEBUG_FS ---help--- Say Y, if you need access to ath9k's statistics for interrupts, rate control, etc. -- cgit v1.2.3-70-g09d2 From 13bda1225072f26603d3aeefc1f14c18b2ab29cd Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 29 Dec 2009 22:57:28 +0800 Subject: ath9k: fix ito64 The unit of sizeof() is byte instead of bit, so fix it. The patch can fix debug output of some dma_addr_t variables. Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index e2cef2ff5d8..1597a42731e 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -33,11 +33,11 @@ struct ath_node; /* Macro to expand scalars to 64-bit objects */ -#define ito64(x) (sizeof(x) == 8) ? \ +#define ito64(x) (sizeof(x) == 1) ? \ (((unsigned long long int)(x)) & (0xff)) : \ - (sizeof(x) == 16) ? \ + (sizeof(x) == 2) ? \ (((unsigned long long int)(x)) & 0xffff) : \ - ((sizeof(x) == 32) ? \ + ((sizeof(x) == 4) ? \ (((unsigned long long int)(x)) & 0xffffffff) : \ (unsigned long long int)(x)) -- cgit v1.2.3-70-g09d2 From 90852f7aed0f90d443efd7e0f9b82d8ac8186848 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 2 Jan 2010 10:31:42 +0100 Subject: mwl8k: fix configure_filter() memory leak on error If there was an error acquiring the firmware lock in mwl8k_configure_filter(), we would end up leaking the multicast command packet prepared by mwl8k_prepare_multicast(). Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 59d49159cf2..59f92105b0c 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3157,8 +3157,10 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, /* Clear unsupported feature flags */ *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC; - if (mwl8k_fw_lock(hw)) + if (mwl8k_fw_lock(hw)) { + kfree(cmd); return; + } if (priv->sniffer_enabled) { mwl8k_enable_sniffer(hw, 0); -- cgit v1.2.3-70-g09d2 From 8a9ac160e844c7ce8074f6aa531feefb4acdee7c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 3 Jan 2010 11:19:35 +0200 Subject: iwl: off by one bug tid is used as an array offset. agg = &priv->stations[sta_id].tid[tid].agg; iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); It should be limitted to MAX_TID_COUNT - 1; struct iwl_tid_data tid[MAX_TID_COUNT]; regards, dan carpenter Signed-off-by: Dan Carpenter CC: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 484c5fdf7c2..761aab127e7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1961,7 +1961,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, struct ieee80211_tx_info *info; struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->u.status); - int tid = MAX_TID_COUNT; + int tid = MAX_TID_COUNT - 1; int sta_id; int freed; u8 *qc = NULL; -- cgit v1.2.3-70-g09d2 From 7de3c5dc0ac89b847b00f25d16976c158dc38e4c Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Sun, 3 Jan 2010 10:20:01 +0100 Subject: zd1211rw: Fix multicast filtering. If multicast parameter (as returned by zd_op_prepare_multicast) has changed, no bit in changed_flags is set. To handle this situation, we do not return if changed_flags is 0. If we do so, we will have some issue with IPv6 which uses multicast for link layer address resolution. Signed-off-by: Benoit Papillault Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_mac.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index cc648efb8ed..9d9b263733e 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -987,12 +987,13 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw, changed_flags &= SUPPORTED_FIF_FLAGS; *new_flags &= SUPPORTED_FIF_FLAGS; - /* changed_flags is always populated but this driver - * doesn't support all FIF flags so its possible we don't - * need to do anything */ - if (!changed_flags) - return; - + /* + * If multicast parameter (as returned by zd_op_prepare_multicast) + * has changed, no bit in changed_flags is set. To handle this + * situation, we do not return if changed_flags is 0. If we do so, + * we will have some issue with IPv6 which uses multicast for link + * layer address resolution. + */ if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) zd_mc_add_all(&hash); -- cgit v1.2.3-70-g09d2 From 359207c687cc8f4f9845c8dadd0d6dabad44e584 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 4 Jan 2010 10:40:39 -0500 Subject: ath5k: Fix eeprom checksum check for custom sized eeproms Commit 8bf3d79bc401ca417ccf9fc076d3295d1a71dbf5 enabled EEPROM checksum checks to avoid bogus bug reports but failed to address updating the code to consider devices with custom EEPROM sizes. Devices with custom sized EEPROMs have the upper limit size stuffed in the EEPROM. Use this as the upper limit instead of the static default size. In case of a checksum error also provide back the max size and whether or not this was the default size or a custom one. If the EEPROM is busted we add a failsafe check to ensure we don't loop forever or try to read bogus areas of hardware. This closes bug 14874 http://bugzilla.kernel.org/show_bug.cgi?id=14874 Cc: stable@kernel.org Cc: David Quan Cc: Stephen Beahm Reported-by: Joshua Covington Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/eeprom.c | 32 +++++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath5k/eeprom.h | 8 ++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 79188526260..9a96550006a 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -97,7 +97,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; int ret; u16 val; - u32 cksum, offset; + u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX; /* * Read values from EEPROM and store them in the capability structure @@ -116,12 +116,38 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) * Validate the checksum of the EEPROM date. There are some * devices with invalid EEPROMs. */ - for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { + AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_UPPER, val); + if (val) { + eep_max = (val & AR5K_EEPROM_SIZE_UPPER_MASK) << + AR5K_EEPROM_SIZE_ENDLOC_SHIFT; + AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_LOWER, val); + eep_max = (eep_max | val) - AR5K_EEPROM_INFO_BASE; + + /* + * Fail safe check to prevent stupid loops due + * to busted EEPROMs. XXX: This value is likely too + * big still, waiting on a better value. + */ + if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) { + ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: " + "%d (0x%04x) max expected: %d (0x%04x)\n", + eep_max, eep_max, + 3 * AR5K_EEPROM_INFO_MAX, + 3 * AR5K_EEPROM_INFO_MAX); + return -EIO; + } + } + + for (cksum = 0, offset = 0; offset < eep_max; offset++) { AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); cksum ^= val; } if (cksum != AR5K_EEPROM_INFO_CKSUM) { - ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); + ATH5K_ERR(ah->ah_sc, "Invalid EEPROM " + "checksum: 0x%04x eep_max: 0x%04x (%s)\n", + cksum, eep_max, + eep_max == AR5K_EEPROM_INFO_MAX ? + "default size" : "custom size"); return -EIO; } diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 0123f3521a0..473a483bb9c 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -37,6 +37,14 @@ #define AR5K_EEPROM_RFKILL_POLARITY_S 1 #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ + +/* FLASH(EEPROM) Defines for AR531X chips */ +#define AR5K_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */ +#define AR5K_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */ +#define AR5K_EEPROM_SIZE_UPPER_MASK 0xfff0 +#define AR5K_EEPROM_SIZE_UPPER_SHIFT 4 +#define AR5K_EEPROM_SIZE_ENDLOC_SHIFT 12 + #define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) -- cgit v1.2.3-70-g09d2 From b59a52f12e483b79e7d32da7ec30dcf3b2e0210b Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Wed, 30 Dec 2009 11:36:29 +0100 Subject: rt2x00: use correct headroom for transmission Use rt2x00dev->ops->extra_tx_headroom, not rt2x00dev->hw->extra_tx_headroom in the tx code, as the later may include other headroom not to be used in the chipset driver. Signed-off-by: Pavel Roskin Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 239afc7a9c0..9915a09141e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -104,7 +104,7 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) * is also mapped to the DMA so it can be used for transfering * additional descriptor information to the hardware. */ - skb_push(skb, rt2x00dev->hw->extra_tx_headroom); + skb_push(skb, rt2x00dev->ops->extra_tx_headroom); skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE); @@ -112,7 +112,7 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) /* * Restore data pointer to original location again. */ - skb_pull(skb, rt2x00dev->hw->extra_tx_headroom); + skb_pull(skb, rt2x00dev->ops->extra_tx_headroom); skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; } @@ -134,7 +134,7 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) * by the driver, but it was actually mapped to DMA. */ dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, - skb->len + rt2x00dev->hw->extra_tx_headroom, + skb->len + rt2x00dev->ops->extra_tx_headroom, DMA_TO_DEVICE); skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; } -- cgit v1.2.3-70-g09d2 From 301a8234ea81938f0f083ae4e274d9c9296f3c86 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 30 Dec 2009 11:36:33 +0100 Subject: rt2x00: Fix LED configuration setting for rt2800. rt2800_blink_set uses an illegal value to set the LED_CFG_G_LED_MODE field of the LED_CFG register. This field is only 2 bits large, so should be initialized with value that fits. Use default value from the vendor driver. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 27bf887f145..9deae41cb78 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -340,7 +340,7 @@ static int rt2800_blink_set(struct led_classdev *led_cdev, rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); - rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); + rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 3); rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); rt2800_register_write(led->rt2x00dev, LED_CFG, reg); -- cgit v1.2.3-70-g09d2 From 7a4a77b7771164d61ce702a588067d1e1d66db7c Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 30 Dec 2009 11:36:30 +0100 Subject: rt2x00: Properly request tx headroom for alignment operations. Current rt2x00 drivers may result in a "ieee80211_tx_status: headroom too small" error message when a frame needs to be properly aligned before transmitting it. This is because the space needed to ensure proper alignment isn't requested from mac80211. Fix this by adding sufficient amount of alignment space to the amount of headroom requested for TX frames. Reported-by: David Ellingsworth Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 6 ++++++ drivers/net/wireless/rt2x00/rt2x00dev.c | 12 +++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 4d841c07c97..dcfc8c25d1a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -112,6 +112,12 @@ #define ALIGN_SIZE(__skb, __header) \ ( ((unsigned long)((__skb)->data + (__header))) & 3 ) +/* + * Constants for extra TX headroom for alignment purposes. + */ +#define RT2X00_ALIGN_SIZE 4 /* Only whole frame needs alignment */ +#define RT2X00_L2PAD_SIZE 8 /* Both header & payload need alignment */ + /* * Standard timing and size defines. * These values should follow the ieee80211 specifications. diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 06c43ca39bf..265e66dba55 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -686,7 +686,17 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) /* * Initialize extra TX headroom required. */ - rt2x00dev->hw->extra_tx_headroom = rt2x00dev->ops->extra_tx_headroom; + rt2x00dev->hw->extra_tx_headroom = + max_t(unsigned int, IEEE80211_TX_STATUS_HEADROOM, + rt2x00dev->ops->extra_tx_headroom); + + /* + * Take TX headroom required for alignment into account. + */ + if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) + rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE; + else if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) + rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE; /* * Register HW. -- cgit v1.2.3-70-g09d2 From 59b015133cd0034f5904a76969d73476380aac46 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 5 Jan 2010 17:56:02 -0800 Subject: Input: serio - fix potential deadlock when unbinding drivers sysfs_remove_group() waits for sysfs attributes to be removed, therefore we do not need to worry about driver-specific attributes being accessed after driver has been detached from the device. In fact, attempts to take serio->drv_mutex in attribute methods may lead to the following deadlock: sysfs_read_file() fill_read_buffer() sysfs_get_active_two() psmouse_attr_show_helper() serio_pin_driver() serio_disconnect_driver() mutex_lock(&serio->drv_mutex); <--------> mutex_lock(&serio_drv_mutex); psmouse_disconnect() sysfs_remove_group(... psmouse_attr_group); .... sysfs_deactivate(); wait_for_completion(); Fix this by removing calls to serio_[un]pin_driver() and functions themselves and using driver-private mutexes to serialize access to attribute's set() methods that may change device state. Signed-off-by: Eric W. Biederman Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 59 ++++++++++++++++---------------------- drivers/input/mouse/psmouse-base.c | 32 ++------------------- include/linux/serio.h | 19 ------------ 3 files changed, 28 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 1f5e2ce327d..1cf32a7814d 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -225,8 +225,10 @@ struct atkbd { struct delayed_work event_work; unsigned long event_jiffies; - struct mutex event_mutex; unsigned long event_mask; + + /* Serializes reconnect(), attr->set() and event work */ + struct mutex mutex; }; /* @@ -577,7 +579,7 @@ static void atkbd_event_work(struct work_struct *work) { struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work); - mutex_lock(&atkbd->event_mutex); + mutex_lock(&atkbd->mutex); if (!atkbd->enabled) { /* @@ -596,7 +598,7 @@ static void atkbd_event_work(struct work_struct *work) atkbd_set_repeat_rate(atkbd); } - mutex_unlock(&atkbd->event_mutex); + mutex_unlock(&atkbd->mutex); } /* @@ -612,7 +614,7 @@ static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit) atkbd->event_jiffies = jiffies; set_bit(event_bit, &atkbd->event_mask); - wmb(); + mb(); schedule_delayed_work(&atkbd->event_work, delay); } @@ -849,12 +851,13 @@ static void atkbd_disconnect(struct serio *serio) { struct atkbd *atkbd = serio_get_drvdata(serio); + sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); + atkbd_disable(atkbd); /* make sure we don't have a command in flight */ cancel_delayed_work_sync(&atkbd->event_work); - sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); input_unregister_device(atkbd->dev); serio_close(serio); serio_set_drvdata(serio, NULL); @@ -1087,7 +1090,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd->dev = dev; ps2_init(&atkbd->ps2dev, serio); INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work); - mutex_init(&atkbd->event_mutex); + mutex_init(&atkbd->mutex); switch (serio->id.type) { @@ -1160,19 +1163,23 @@ static int atkbd_reconnect(struct serio *serio) { struct atkbd *atkbd = serio_get_drvdata(serio); struct serio_driver *drv = serio->drv; + int retval = -1; if (!atkbd || !drv) { printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n"); return -1; } + mutex_lock(&atkbd->mutex); + atkbd_disable(atkbd); if (atkbd->write) { if (atkbd_probe(atkbd)) - return -1; + goto out; + if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) - return -1; + goto out; atkbd_activate(atkbd); @@ -1190,8 +1197,11 @@ static int atkbd_reconnect(struct serio *serio) } atkbd_enable(atkbd); + retval = 0; - return 0; + out: + mutex_unlock(&atkbd->mutex); + return retval; } static struct serio_device_id atkbd_serio_ids[] = { @@ -1235,47 +1245,28 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, ssize_t (*handler)(struct atkbd *, char *)) { struct serio *serio = to_serio_port(dev); - int retval; - - retval = serio_pin_driver(serio); - if (retval) - return retval; - - if (serio->drv != &atkbd_drv) { - retval = -ENODEV; - goto out; - } - - retval = handler((struct atkbd *)serio_get_drvdata(serio), buf); + struct atkbd *atkbd = serio_get_drvdata(serio); -out: - serio_unpin_driver(serio); - return retval; + return handler(atkbd, buf); } static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, ssize_t (*handler)(struct atkbd *, const char *, size_t)) { struct serio *serio = to_serio_port(dev); - struct atkbd *atkbd; + struct atkbd *atkbd = serio_get_drvdata(serio); int retval; - retval = serio_pin_driver(serio); + retval = mutex_lock_interruptible(&atkbd->mutex); if (retval) return retval; - if (serio->drv != &atkbd_drv) { - retval = -ENODEV; - goto out; - } - - atkbd = serio_get_drvdata(serio); atkbd_disable(atkbd); retval = handler(atkbd, buf, count); atkbd_enable(atkbd); -out: - serio_unpin_driver(serio); + mutex_unlock(&atkbd->mutex); + return retval; } diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 401ac6b6edd..d59e18b24ed 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1450,24 +1450,10 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de struct serio *serio = to_serio_port(dev); struct psmouse_attribute *attr = to_psmouse_attr(devattr); struct psmouse *psmouse; - int retval; - - retval = serio_pin_driver(serio); - if (retval) - return retval; - - if (serio->drv != &psmouse_drv) { - retval = -ENODEV; - goto out; - } psmouse = serio_get_drvdata(serio); - retval = attr->show(psmouse, attr->data, buf); - -out: - serio_unpin_driver(serio); - return retval; + return attr->show(psmouse, attr->data, buf); } ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr, @@ -1478,18 +1464,9 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev struct psmouse *psmouse, *parent = NULL; int retval; - retval = serio_pin_driver(serio); - if (retval) - return retval; - - if (serio->drv != &psmouse_drv) { - retval = -ENODEV; - goto out_unpin; - } - retval = mutex_lock_interruptible(&psmouse_mutex); if (retval) - goto out_unpin; + goto out; psmouse = serio_get_drvdata(serio); @@ -1519,8 +1496,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev out_unlock: mutex_unlock(&psmouse_mutex); - out_unpin: - serio_unpin_driver(serio); + out: return retval; } @@ -1582,9 +1558,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co } mutex_unlock(&psmouse_mutex); - serio_unpin_driver(serio); serio_unregister_child_port(serio); - serio_pin_driver_uninterruptible(serio); mutex_lock(&psmouse_mutex); if (serio->drv != &psmouse_drv) { diff --git a/include/linux/serio.h b/include/linux/serio.h index e2f3044d4a4..813d26c247e 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h @@ -136,25 +136,6 @@ static inline void serio_continue_rx(struct serio *serio) spin_unlock_irq(&serio->lock); } -/* - * Use the following functions to pin serio's driver in process context - */ -static inline int serio_pin_driver(struct serio *serio) -{ - return mutex_lock_interruptible(&serio->drv_mutex); -} - -static inline void serio_pin_driver_uninterruptible(struct serio *serio) -{ - mutex_lock(&serio->drv_mutex); -} - -static inline void serio_unpin_driver(struct serio *serio) -{ - mutex_unlock(&serio->drv_mutex); -} - - #endif /* -- cgit v1.2.3-70-g09d2 From 0ef7a26af1278f7ec0b718148e88f01ba1953835 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 Jan 2010 17:56:02 -0800 Subject: Input: atkbd - fix canceling event_work in disconnect We need to first unregister input device and only then cancel event work since events can arrive (and cause event work to get scheduled again) until input_unregister_device() returns. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 1cf32a7814d..7b4056292ea 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -855,10 +855,16 @@ static void atkbd_disconnect(struct serio *serio) atkbd_disable(atkbd); - /* make sure we don't have a command in flight */ + input_unregister_device(atkbd->dev); + + /* + * Make sure we don't have a command in flight. + * Note that since atkbd->enabled is false event work will keep + * rescheduling itself until it gets canceled and will not try + * accessing freed input device or serio port. + */ cancel_delayed_work_sync(&atkbd->event_work); - input_unregister_device(atkbd->dev); serio_close(serio); serio_set_drvdata(serio, NULL); kfree(atkbd); -- cgit v1.2.3-70-g09d2 From 30a589fde0162aa4dac7c69803aeee8fbe8d1b82 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 5 Jan 2010 17:56:04 -0800 Subject: Input: evdev - be less aggressive about sending SIGIO notifies When using realtime signals, we'll enqueue one signal for every event. This is unfortunate, because (for example) keyboard presses are three events: key, msc scancode, and syn. They'll be enqueued fast enough in kernel space that all three events will be ready to read by the time userspace runs, so the first invocation of the signal handler will read all three events, but then the second two invocations still have to run to do no work. Instead, only send the SIGIO notification on syn events. This is a slight abuse of SIGIO semantics, in principle it ought to fire as soon as any events are readable. But it matches evdev semantics, which is more important since SIGIO is rather vaguely defined to begin with. Signed-off-by: Adam Jackson Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index dee6706038a..258c639571b 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -59,7 +59,8 @@ static void evdev_pass_event(struct evdev_client *client, client->head &= EVDEV_BUFFER_SIZE - 1; spin_unlock(&client->buffer_lock); - kill_fasync(&client->fasync, SIGIO, POLL_IN); + if (event->type == EV_SYN) + kill_fasync(&client->fasync, SIGIO, POLL_IN); } /* -- cgit v1.2.3-70-g09d2 From 861a64428c0786a5cfa2ffb36b2f8058dea5dda0 Mon Sep 17 00:00:00 2001 From: Miguel Aguilar Date: Wed, 6 Jan 2010 00:06:50 -0800 Subject: Input: davinci_keyscan - add device_enable method to platform data Add a function pointer in the platform data of the DaVinci Keyscan driver called device_enable, in order to perform board specific actions when the device is initialized, like setup the PINMUX configuration. Signed-off-by: Miguel Aguilar Signed-off-by: Kevin Hilman Signed-off-by: Dmitry Torokhov --- arch/arm/mach-davinci/include/mach/keyscan.h | 1 + drivers/input/keyboard/davinci_keyscan.c | 8 ++++++++ 2 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/arch/arm/mach-davinci/include/mach/keyscan.h b/arch/arm/mach-davinci/include/mach/keyscan.h index b4e21a2976d..7a560e05bda 100644 --- a/arch/arm/mach-davinci/include/mach/keyscan.h +++ b/arch/arm/mach-davinci/include/mach/keyscan.h @@ -29,6 +29,7 @@ enum davinci_matrix_types { }; struct davinci_ks_platform_data { + int (*device_enable)(struct device *dev); unsigned short *keymap; u32 keymapsize; u8 rep:1; diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index 6e52d855f63..d410d7a52f1 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -174,6 +174,14 @@ static int __init davinci_ks_probe(struct platform_device *pdev) struct davinci_ks_platform_data *pdata = pdev->dev.platform_data; int error, i; + if (pdata->device_enable) { + error = pdata->device_enable(dev); + if (error < 0) { + dev_dbg(dev, "device enable function failed\n"); + return error; + } + } + if (!pdata->keymap) { dev_dbg(dev, "no keymap from pdata\n"); return -EINVAL; -- cgit v1.2.3-70-g09d2 From 6f2701b79f2ee0c5eb946e8a87993acbe8041da3 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Wed, 6 Jan 2010 00:32:48 -0800 Subject: Input: bcm5974 - report ABS_MT events Make bcm5974 report raw multi-touch (MT) data in the form of ABS_MT events. [dtor@mail.ru: get rid of module option, always report all events] Signed-off-by: Henrik Rydberg Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/bcm5974.c | 44 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 0d1d33468b4..4f8fe0886b2 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -139,6 +139,7 @@ struct tp_finger { /* trackpad finger data size, empirically at least ten fingers */ #define SIZEOF_FINGER sizeof(struct tp_finger) #define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) +#define MAX_FINGER_ORIENTATION 16384 /* device-specific parameters */ struct bcm5974_param { @@ -284,6 +285,26 @@ static void setup_events_to_report(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_Y, 0, cfg->y.dim, cfg->y.fuzz, 0); + /* finger touch area */ + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); + /* finger approach area */ + input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); + /* finger orientation */ + input_set_abs_params(input_dev, ABS_MT_ORIENTATION, + -MAX_FINGER_ORIENTATION, + MAX_FINGER_ORIENTATION, 0, 0); + /* finger position */ + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + cfg->x.devmin, cfg->x.devmax, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + cfg->y.devmin, cfg->y.devmax, 0, 0); + __set_bit(EV_KEY, input_dev->evbit); __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(BTN_TOOL_FINGER, input_dev->keybit); @@ -310,13 +331,29 @@ static int report_bt_state(struct bcm5974 *dev, int size) return 0; } +static void report_finger_data(struct input_dev *input, + const struct bcm5974_config *cfg, + const struct tp_finger *f) +{ + input_report_abs(input, ABS_MT_TOUCH_MAJOR, raw2int(f->force_major)); + input_report_abs(input, ABS_MT_TOUCH_MINOR, raw2int(f->force_minor)); + input_report_abs(input, ABS_MT_WIDTH_MAJOR, raw2int(f->size_major)); + input_report_abs(input, ABS_MT_WIDTH_MINOR, raw2int(f->size_minor)); + input_report_abs(input, ABS_MT_ORIENTATION, + MAX_FINGER_ORIENTATION - raw2int(f->orientation)); + input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x)); + input_report_abs(input, ABS_MT_POSITION_Y, + cfg->y.devmin + cfg->y.devmax - raw2int(f->abs_y)); + input_mt_sync(input); +} + /* report trackpad data as logical trackpad state */ static int report_tp_state(struct bcm5974 *dev, int size) { const struct bcm5974_config *c = &dev->cfg; const struct tp_finger *f; struct input_dev *input = dev->input; - int raw_p, raw_w, raw_x, raw_y, raw_n; + int raw_p, raw_w, raw_x, raw_y, raw_n, i; int ptest, origin, ibt = 0, nmin = 0, nmax = 0; int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; @@ -329,6 +366,11 @@ static int report_tp_state(struct bcm5974 *dev, int size) /* always track the first finger; when detached, start over */ if (raw_n) { + + /* report raw trackpad data */ + for (i = 0; i < raw_n; i++) + report_finger_data(input, c, &f[i]); + raw_p = raw2int(f->force_major); raw_w = raw2int(f->size_major); raw_x = raw2int(f->abs_x); -- cgit v1.2.3-70-g09d2 From e4e6efd2df4b5754bd519b516207eb723d1f17df Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 7 Jan 2010 01:52:39 -0800 Subject: Input: psmouse - fix Synaptics detection when protocol is disabled For configurations where Synaptics hardware is present but the Synaptics extensions support is not compiled in, the mouse is reprobed and a new device is allocated on every suspend/resume. During probe, psmouse_switch_protocol() calls psmouse_extensions() with set_properties=1. This calls the dummy synaptics_init() which returns an error code, instructing us not to use the synaptics extensions. During resume, psmouse_reconnect() calls psmouse_extensions() with set_properties=0, in which case call to synaptics_init() is bypassed and PSMOUSE_SYNAPTICS is returned. Since the result is different from previous attempt psmouse_reconnect() fails and full re-probe happens. Fix this by tweaking the set_properties=0 codepath in psmouse_extensions() to be more careful about offering PSMOUSE_SYNAPTICS extensions. Signed-off-by: Daniel Drake Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 9 ++++++++- drivers/input/mouse/synaptics.c | 10 ++++++++++ drivers/input/mouse/synaptics.h | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index d59e18b24ed..cabf4e1caac 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -627,8 +627,15 @@ static int psmouse_extensions(struct psmouse *psmouse, synaptics_hardware = true; if (max_proto > PSMOUSE_IMEX) { - if (!set_properties || synaptics_init(psmouse) == 0) +/* + * Try activating protocol, but check if support is enabled first, since + * we try detecting Synaptics even when protocol is disabled. + */ + if (synaptics_supported() && + (!set_properties || synaptics_init(psmouse) == 0)) { return PSMOUSE_SYNAPTICS; + } + /* * Some Synaptics touchpads can emulate extended protocols (like IMPS/2). * Unfortunately Logitech/Genius probes confuse some firmware versions so diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 05689e73219..d3f5243fa09 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -743,6 +743,11 @@ int synaptics_init(struct psmouse *psmouse) return -1; } +bool synaptics_supported(void) +{ + return true; +} + #else /* CONFIG_MOUSE_PS2_SYNAPTICS */ void __init synaptics_module_init(void) @@ -754,5 +759,10 @@ int synaptics_init(struct psmouse *psmouse) return -ENOSYS; } +bool synaptics_supported(void) +{ + return false; +} + #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 838e7f2c9b3..f0f40a331dc 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -109,5 +109,6 @@ void synaptics_module_init(void); int synaptics_detect(struct psmouse *psmouse, bool set_properties); int synaptics_init(struct psmouse *psmouse); void synaptics_reset(struct psmouse *psmouse); +bool synaptics_supported(void); #endif /* _SYNAPTICS_H */ -- cgit v1.2.3-70-g09d2 From 36bfc7e2100ab3f9891bb779c36d5e685f253509 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Tue, 5 Jan 2010 19:33:54 +0100 Subject: drbd: check on CONFIG_LBDAF, not LBD It is called LBDAF since 2.6.31. impact: without this change, on 32bit, DRBD would wrongly claim to only support 2TiB devices. Signed-off-by: Lars Ellenberg Signed-off-by: Philipp Reisner --- drivers/block/drbd/drbd_int.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index c9755876343..79d8e22c4d0 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1275,7 +1275,7 @@ struct bm_extent { #if DRBD_MAX_SECTORS_BM < DRBD_MAX_SECTORS_32 #define DRBD_MAX_SECTORS DRBD_MAX_SECTORS_BM #define DRBD_MAX_SECTORS_FLEX DRBD_MAX_SECTORS_BM -#elif !defined(CONFIG_LBD) && BITS_PER_LONG == 32 +#elif !defined(CONFIG_LBDAF) && BITS_PER_LONG == 32 #define DRBD_MAX_SECTORS DRBD_MAX_SECTORS_32 #define DRBD_MAX_SECTORS_FLEX DRBD_MAX_SECTORS_32 #else -- cgit v1.2.3-70-g09d2 From 8fcc501831aa5b37a4a5a8cd9dc965be3cacc599 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 28 Dec 2009 13:15:20 +0800 Subject: drm/i915: disable TV hotplug status check As we removed TV hotplug, don't check its status ever. Reviewed-by: Adam Jackson Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_tv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 1d5b9b7b033..552ec110b74 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1840,8 +1840,6 @@ intel_tv_init(struct drm_device *dev) drm_connector_attach_property(connector, dev->mode_config.tv_bottom_margin_property, tv_priv->margin[TV_MARGIN_BOTTOM]); - - dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS; out: drm_sysfs_connector_add(connector); } -- cgit v1.2.3-70-g09d2 From 40f33a92100f4d9b6e85ad642100cfe42d7ff57d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 13:30:36 +0800 Subject: drm/i915: Add HP nx9020/SamsungSX20S to ACPI LID quirk list The HP comaq nx9020/Samsung SX20S laptop always report that the LID status is closed and we can't use it reliabily for LVDS detection. So add the two boxes into the quirk list. http://bugzilla.kernel.org/show_bug.cgi?id=14957 http://bugzilla.kernel.org/show_bug.cgi?id=14554 Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_lvds.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f4b4aa242df..5041590dfdc 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -601,6 +601,20 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, /* Some lid devices report incorrect lid status, assume they're connected */ static const struct dmi_system_id bad_lid_status[] = { + { + .ident = "Compaq nx9020", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_BOARD_NAME, "3084"), + }, + }, + { + .ident = "Samsung SX20S", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_BOARD_NAME, "SX20S"), + }, + }, { .ident = "Aspire One", .matches = { -- cgit v1.2.3-70-g09d2 From ddc9003c357d1ce10be6ec91bdb8df8ea836087d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 22:05:56 +0800 Subject: drm/i915: Use find_pll function to calculate DPLL setting for LVDS downclock For any given clock we can use the find_pll to get the corresponding DPLL setting. It is unnecessary to use the find_reduce_pll callback function to calculate the DPLL parameter for LVDS downclock in order to get the same divider factor(P) for the normal and downclock. In theory when the LVDS downclock is supported by LVDS panel, we should get the same DPLL divider factor(P) for the normal clock and reduced downclock. If we get the diferent divider factor(P) for normal clock and reduced downclock, it means that the found downclock is incorrect and should be discarded. So we should use find_pll callback to calculate the DPLL parameter for the LVDS reduced downclock as for the normal clock. Then we can do the cleanup about find_reduced_pll. Signed-off-by: Zhao Yakui cc: Jesse Barnes cc: Matthew Garrett Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 61 ++---------------------------------- 1 file changed, 2 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 002612fae71..0cf44d6e9de 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -70,8 +70,6 @@ struct intel_limit { intel_p2_t p2; bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, int, int, intel_clock_t *); - bool (* find_reduced_pll)(const intel_limit_t *, struct drm_crtc *, - int, int, intel_clock_t *); }; #define I8XX_DOT_MIN 25000 @@ -274,9 +272,6 @@ static bool intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); static bool -intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); -static bool intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); @@ -299,7 +294,6 @@ static const intel_limit_t intel_limits_i8xx_dvo = { .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_i8xx_lvds = { @@ -314,7 +308,6 @@ static const intel_limit_t intel_limits_i8xx_lvds = { .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_i9xx_sdvo = { @@ -329,7 +322,6 @@ static const intel_limit_t intel_limits_i9xx_sdvo = { .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_i9xx_lvds = { @@ -347,7 +339,6 @@ static const intel_limit_t intel_limits_i9xx_lvds = { .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; /* below parameter and function is for G4X Chipset Family*/ @@ -365,7 +356,6 @@ static const intel_limit_t intel_limits_g4x_sdvo = { .p2_fast = G4X_P2_SDVO_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_hdmi = { @@ -382,7 +372,6 @@ static const intel_limit_t intel_limits_g4x_hdmi = { .p2_fast = G4X_P2_HDMI_DAC_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_single_channel_lvds = { @@ -407,7 +396,6 @@ static const intel_limit_t intel_limits_g4x_single_channel_lvds = { .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { @@ -432,7 +420,6 @@ static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_display_port = { @@ -470,7 +457,6 @@ static const intel_limit_t intel_limits_pineview_sdvo = { .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_pineview_lvds = { @@ -486,7 +472,6 @@ static const intel_limit_t intel_limits_pineview_lvds = { .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_ironlake_sdvo = { @@ -768,46 +753,6 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, return (err != target); } - -static bool -intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) - -{ - struct drm_device *dev = crtc->dev; - intel_clock_t clock; - int err = target; - bool found = false; - - memcpy(&clock, best_clock, sizeof(intel_clock_t)); - - for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { - for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) { - /* m1 is always 0 in Pineview */ - if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev)) - break; - for (clock.n = limit->n.min; clock.n <= limit->n.max; - clock.n++) { - int this_err; - - intel_clock(dev, refclk, &clock); - - if (!intel_PLL_is_valid(crtc, &clock)) - continue; - - this_err = abs(clock.dot - target); - if (this_err < err) { - *best_clock = clock; - err = this_err; - found = true; - } - } - } - } - - return found; -} - static bool intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock) @@ -2910,10 +2855,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return -EINVAL; } - if (is_lvds && limit->find_reduced_pll && - dev_priv->lvds_downclock_avail) { - memcpy(&reduced_clock, &clock, sizeof(intel_clock_t)); - has_reduced_clock = limit->find_reduced_pll(limit, crtc, + if (is_lvds && dev_priv->lvds_downclock_avail) { + has_reduced_clock = limit->find_pll(limit, crtc, dev_priv->lvds_downclock, refclk, &reduced_clock); -- cgit v1.2.3-70-g09d2 From a59e385eacd920222756a23c113444fe3063cf81 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 22:05:57 +0800 Subject: drm/i915: Fix Ironlake M/N/P ranges to match the spec Without this fix, some modes couldn't find appropriate clocks. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt Tested-by: Matthew Garrett --- drivers/gpu/drm/i915/intel_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0cf44d6e9de..42e8c031c2c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -241,11 +241,11 @@ struct intel_limit { #define IRONLAKE_VCO_MIN 1760000 #define IRONLAKE_VCO_MAX 3510000 #define IRONLAKE_N_MIN 1 -#define IRONLAKE_N_MAX 5 +#define IRONLAKE_N_MAX 6 #define IRONLAKE_M_MIN 79 -#define IRONLAKE_M_MAX 118 +#define IRONLAKE_M_MAX 127 #define IRONLAKE_M1_MIN 12 -#define IRONLAKE_M1_MAX 23 +#define IRONLAKE_M1_MAX 22 #define IRONLAKE_M2_MIN 5 #define IRONLAKE_M2_MAX 9 #define IRONLAKE_P_SDVO_DAC_MIN 5 -- cgit v1.2.3-70-g09d2 From 992dc9ae61f86db3b8ef9f8d6b7df898c90e8c08 Mon Sep 17 00:00:00 2001 From: David John Date: Thu, 31 Dec 2009 12:00:46 +0530 Subject: drm: Keep disabled outputs disabled after suspend / resume With the current DRM code, an output that has been powered off from userspace will automatically power back on when resuming from suspend. This patch fixes this behaviour. Tested only with the Intel i915 driver on an Intel GM45 Express chipset. Signed-off-by: David John Reviewed-by: Jesse Barnes Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc_helper.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 4231d6db72e..aba79c49458 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -216,7 +216,7 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc) EXPORT_SYMBOL(drm_helper_crtc_in_use); /** - * drm_disable_unused_functions - disable unused objects + * drm_helper_disable_unused_functions - disable unused objects * @dev: DRM device * * LOCKING: @@ -1162,6 +1162,9 @@ EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); int drm_helper_resume_force_mode(struct drm_device *dev) { struct drm_crtc *crtc; + struct drm_encoder *encoder; + struct drm_encoder_helper_funcs *encoder_funcs; + struct drm_crtc_helper_funcs *crtc_funcs; int ret; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -1174,6 +1177,25 @@ int drm_helper_resume_force_mode(struct drm_device *dev) if (ret == false) DRM_ERROR("failed to set mode on crtc %p\n", crtc); + + /* Turn off outputs that were already powered off */ + if (drm_helper_choose_crtc_dpms(crtc)) { + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + + if(encoder->crtc != crtc) + continue; + + encoder_funcs = encoder->helper_private; + if (encoder_funcs->dpms) + (*encoder_funcs->dpms) (encoder, + drm_helper_choose_encoder_dpms(encoder)); + + crtc_funcs = crtc->helper_private; + if (crtc_funcs->dpms) + (*crtc_funcs->dpms) (crtc, + drm_helper_choose_crtc_dpms(crtc)); + } + } } /* disable the unused connectors while restoring the modesetting */ drm_helper_disable_unused_functions(dev); -- cgit v1.2.3-70-g09d2 From 7751b8cb754f1bc48b20c1145d43c7651d4951fd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 8 Jan 2010 09:27:08 +1000 Subject: drm/kms/fb: check for depth changes from userspace for resizing. If userspace (plymouth in this case) asks for a deeper depth, refuse it as well due to lack of resizing. This fixes an issue since < 32MB cards went to 8bpp and plymouth crashes on startup. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 100ee48760b..1c2b7d44ec0 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -606,11 +606,10 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, return -EINVAL; /* Need to resize the fb object !!! */ - if (var->xres > fb->width || var->yres > fb->height) { - DRM_ERROR("Requested width/height is greater than current fb " - "object %dx%d > %dx%d\n", var->xres, var->yres, - fb->width, fb->height); - DRM_ERROR("Need resizing code.\n"); + if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) { + DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb " + "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel, + fb->width, fb->height, fb->bits_per_pixel); return -EINVAL; } -- cgit v1.2.3-70-g09d2 From c8106d7625a58ee4387cb2efe3e82320ad44b467 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 8 Jan 2010 10:04:30 -0800 Subject: iwlwifi: fix iwl_queue_used bug when read_ptr == write_ptr When txq read_ptr equals to write_ptr, iwl_queue_used should always return false. Because there is no used TFD in this case. This is a complementary fix to the fix already included in commit "iwl3945: fix panic in iwl3945 driver". Both fixes are needed to address the panic below. This problem was discussed on linux-wireless in http://thread.gmane.org/gmane.linux.kernel.wireless.general/43568 <1>[ 7290.414172] IP: [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.414205] PGD 0 <1>[ 7290.414214] Thread overran stack, or stack corrupted <0>[ 7290.414229] Oops: 0002 [#1] PREEMPT SMP <0>[ 7290.414246] last sysfs file: /sys/devices/platform/coretemp.1/temp1_input <4>[ 7290.414265] CPU 0 <4>[ 7290.414274] Modules linked in: af_packet nfsd usb_storage usb_libusual cpufreq_powersave exportfs cpufreq_conservative iwl3945 nfs cpufreq_userspace snd_hda_codec_realtek acpi_cpufreq uvcvideo lockd iwlcore snd_hda_intel joydev coretemp nfs_acl videodev snd_hda_codec mac80211 v4l1_compat snd_hwdep sbp2 v4l2_compat_ioctl32 uhci_hcd psmouse auth_rpcgss ohci1394 cfg80211 ehci_hcd video ieee1394 snd_pcm serio_raw battery ac nvidia(P) usbcore output sunrpc evdev lirc_ene0100 snd_page_alloc rfkill tg3 libphy fuse lzo lzo_decompress lzo_compress <6>[ 7290.414486] Pid: 0, comm: swapper Tainted: P 2.6.32-rc8-wl #213 Aspire 5720 <6>[ 7290.414507] RIP: 0010:[] [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <6>[ 7290.414541] RSP: 0018:ffff880002203d60 EFLAGS: 00010246 <6>[ 7290.414557] RAX: 000000000000004f RBX: ffff880064c11600 RCX: 0000000000000013 <6>[ 7290.414576] RDX: ffffffffa0ddcf20 RSI: ffff8800512b7008 RDI: 0000000000000038 <6>[ 7290.414596] RBP: ffff880002203dd0 R08: 0000000000000000 R09: 0000000000000100 <6>[ 7290.414616] R10: 0000000000000001 R11: 0000000000000000 R12: 00000000000000a0 <6>[ 7290.414635] R13: 0000000000000002 R14: 0000000000000013 R15: 0000000000020201 <6>[ 7290.414655] FS: 0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000 <6>[ 7290.414677] CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b <6>[ 7290.414693] CR2: 0000000000000041 CR3: 0000000001001000 CR4: 00000000000006f0 <6>[ 7290.414712] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 <6>[ 7290.414732] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 <4>[ 7290.414752] Process swapper (pid: 0, threadinfo ffffffff81524000, task ffffffff81528b60) <0>[ 7290.414772] Stack: <4>[ 7290.414780] ffff880002203da0 0000000000000046 0000000000000000 0000000000000046 <4>[ 7290.414804] <0> 0000000000000282 0000000000000282 0000000000000282 ffff880064c12010 <4>[ 7290.414830] <0> ffff880002203db0 ffff880064c11600 ffff880064c12e50 ffff8800512b7000 <0>[ 7290.414858] Call Trace: <0>[ 7290.414867] <4>[ 7290.414884] [] iwl3945_irq_tasklet+0x657/0x1740 [iwl3945] <4>[ 7290.414910] [] ? _spin_unlock+0x30/0x60 <4>[ 7290.414931] [] tasklet_action+0x101/0x110 <4>[ 7290.414950] [] __do_softirq+0xc0/0x160 <4>[ 7290.414968] [] call_softirq+0x1c/0x30 <4>[ 7290.414986] [] do_softirq+0x75/0xb0 <4>[ 7290.415003] [] irq_exit+0x95/0xa0 <4>[ 7290.415020] [] do_IRQ+0x77/0xf0 <4>[ 7290.415038] [] ret_from_intr+0x0/0xf <0>[ 7290.415052] <4>[ 7290.415067] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415087] [] ? acpi_idle_enter_bm+0x27a/0x2a5 <4>[ 7290.415107] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415130] [] ? cpuidle_idle_call+0x93/0xf0 <4>[ 7290.415149] [] ? cpu_idle+0xa7/0x110 <4>[ 7290.415168] [] ? rest_init+0x75/0x80 <4>[ 7290.415187] [] ? start_kernel+0x3a7/0x3b3 <4>[ 7290.415206] [] ? x86_64_start_reservations+0x125/0x129 <4>[ 7290.415227] [] ? x86_64_start_kernel+0xe4/0xeb <0>[ 7290.415243] Code: 00 41 39 ce 0f 8d e8 01 00 00 48 8b 47 40 48 63 d2 48 69 d2 98 00 00 00 4c 8b 04 02 48 c7 c2 20 cf dd a0 49 8d 78 38 49 8d 40 4f 47 09 00 c6 47 0c 00 c6 47 0f 00 c6 47 12 00 c6 47 15 00 49 <1>[ 7290.415382] RIP [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.415410] RSP <0>[ 7290.415421] CR2: 0000000000000041 <4>[ 7290.415436] ---[ end trace ec46807277caa515 ]--- <0>[ 7290.415450] Kernel panic - not syncing: Fatal exception in interrupt <4>[ 7290.415468] Pid: 0, comm: swapper Tainted: P D 2.6.32-rc8-wl #213 <4>[ 7290.415486] Call Trace: <4>[ 7290.415495] [] panic+0x7d/0x13a <4>[ 7290.415519] [] oops_end+0xda/0xe0 <4>[ 7290.415538] [] no_context+0xea/0x250 <4>[ 7290.415557] [] ? select_task_rq_fair+0x511/0x780 <4>[ 7290.415578] [] __bad_area_nosemaphore+0x125/0x1e0 <4>[ 7290.415597] [] ? __enqueue_entity+0x7c/0x80 <4>[ 7290.415616] [] ? enqueue_task_fair+0x111/0x150 <4>[ 7290.415636] [] bad_area_nosemaphore+0xe/0x10 <4>[ 7290.415656] [] do_page_fault+0x26a/0x320 <4>[ 7290.415674] [] page_fault+0x1f/0x30 <4>[ 7290.415697] [] ? iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.415723] [] iwl3945_irq_tasklet+0x657/0x1740 [iwl3945] <4>[ 7290.415746] [] ? _spin_unlock+0x30/0x60 <4>[ 7290.415764] [] tasklet_action+0x101/0x110 <4>[ 7290.415783] [] __do_softirq+0xc0/0x160 <4>[ 7290.415801] [] call_softirq+0x1c/0x30 <4>[ 7290.415818] [] do_softirq+0x75/0xb0 <4>[ 7290.415835] [] irq_exit+0x95/0xa0 <4>[ 7290.415852] [] do_IRQ+0x77/0xf0 <4>[ 7290.415869] [] ret_from_intr+0x0/0xf <4>[ 7290.415883] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415911] [] ? acpi_idle_enter_bm+0x27a/0x2a5 <4>[ 7290.415931] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415952] [] ? cpuidle_idle_call+0x93/0xf0 <4>[ 7290.415971] [] ? cpu_idle+0xa7/0x110 <4>[ 7290.415989] [] ? rest_init+0x75/0x80 <4>[ 7290.416007] [] ? start_kernel+0x3a7/0x3b3 <4>[ 7290.416026] [] ? x86_64_start_reservations+0x125/0x129 <4>[ 7290.416047] [] ? x86_64_start_kernel+0xe4/0xeb Reported-by: Maxim Levitsky Tested-by: Maxim Levitsky Signed-off-by: Zhu Yi Signed-off-by: Reinette Chatre CC: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 165d1f6e2dd..3822cf53e36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -711,7 +711,7 @@ extern void iwl_txq_ctx_stop(struct iwl_priv *priv); extern int iwl_queue_space(const struct iwl_queue *q); static inline int iwl_queue_used(const struct iwl_queue *q, int i) { - return q->write_ptr > q->read_ptr ? + return q->write_ptr >= q->read_ptr ? (i >= q->read_ptr && i < q->write_ptr) : !(i < q->read_ptr && i >= q->write_ptr); } -- cgit v1.2.3-70-g09d2 From c91c3efca5297bd67324654524ced38162f2e579 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 8 Jan 2010 10:04:31 -0800 Subject: iwlwifi: disable tx on beacon update notification On beacon change update notification from mac we are not disabling the tx in adhoc mode. Mac sends BSS_CHANGED_BEACON_ENABLED when station leaves IBSS. Driver should indicate uCode to not to send anything on receiving this notification. Functionality to indicate uCode is duplicated across two notifications so created a common function called iwl_set_no_assoc. Fix the issue at http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2133. Signed-off-by: Abhijeet Kolekar Tested-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 45 ++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 574d3665870..5461f105bd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2344,6 +2344,21 @@ static void iwl_ht_conf(struct iwl_priv *priv, IWL_DEBUG_MAC80211(priv, "leave\n"); } +static inline void iwl_set_no_assoc(struct iwl_priv *priv) +{ + priv->assoc_id = 0; + iwl_led_disassociate(priv); + /* + * inform the ucode that there is no longer an + * association and that no more packets should be + * sent + */ + priv->staging_rxon.filter_flags &= + ~RXON_FILTER_ASSOC_MSK; + priv->staging_rxon.assoc_id = 0; + iwlcore_commit_rxon(priv); +} + #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -2475,20 +2490,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; if (!iwl_is_rfkill(priv)) priv->cfg->ops->lib->post_associate(priv); - } else { - priv->assoc_id = 0; - iwl_led_disassociate(priv); - - /* - * inform the ucode that there is no longer an - * association and that no more packets should be - * send - */ - priv->staging_rxon.filter_flags &= - ~RXON_FILTER_ASSOC_MSK; - priv->staging_rxon.assoc_id = 0; - iwlcore_commit_rxon(priv); - } + } else + iwl_set_no_assoc(priv); } if (changes && iwl_is_associated(priv) && priv->assoc_id) { @@ -2503,12 +2506,14 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, } } - if ((changes & BSS_CHANGED_BEACON_ENABLED) && - vif->bss_conf.enable_beacon) { - memcpy(priv->staging_rxon.bssid_addr, - bss_conf->bssid, ETH_ALEN); - memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); - iwlcore_config_ap(priv); + if (changes & BSS_CHANGED_BEACON_ENABLED) { + if (vif->bss_conf.enable_beacon) { + memcpy(priv->staging_rxon.bssid_addr, + bss_conf->bssid, ETH_ALEN); + memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); + iwlcore_config_ap(priv); + } else + iwl_set_no_assoc(priv); } mutex_unlock(&priv->mutex); -- cgit v1.2.3-70-g09d2 From dd38d6889dc5dae2014d9eac72fae32f477f294e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 9 Jan 2010 00:13:36 -0800 Subject: Input: xbox - do not use GFP_KERNEL under spinlock xbox_play_effect() is called while holding dev->event_lock with interrupts disabled and thus may not use GFP_KERNEL when submitting urbs. Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 482cb1204e4..8a28fb7846d 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -446,7 +446,7 @@ static void xpad_irq_in(struct urb *urb) } exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); + retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", __func__, retval); @@ -571,7 +571,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, xpad->odata[6] = 0x00; xpad->odata[7] = 0x00; xpad->irq_out->transfer_buffer_length = 8; - usb_submit_urb(xpad->irq_out, GFP_KERNEL); + usb_submit_urb(xpad->irq_out, GFP_ATOMIC); } return 0; -- cgit v1.2.3-70-g09d2 From 588d7d1268658b6a010eb7415bff2f936c51acf7 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sun, 13 Dec 2009 20:07:42 +0100 Subject: drm/nouveau: Add cache_flush/pull fifo engine functions. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_drv.h | 4 ++++ drivers/gpu/drm/nouveau/nouveau_state.c | 10 ++++++++++ drivers/gpu/drm/nouveau/nv04_fifo.c | 34 +++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 5f8cbb79c49..48d0ad9434a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -292,6 +292,8 @@ struct nouveau_fifo_engine { void (*disable)(struct drm_device *); void (*enable)(struct drm_device *); bool (*reassign)(struct drm_device *, bool enable); + bool (*cache_flush)(struct drm_device *dev); + bool (*cache_pull)(struct drm_device *dev, bool enable); int (*channel_id)(struct drm_device *); @@ -889,6 +891,8 @@ extern int nv04_fifo_init(struct drm_device *); extern void nv04_fifo_disable(struct drm_device *); extern void nv04_fifo_enable(struct drm_device *); extern bool nv04_fifo_reassign(struct drm_device *, bool); +extern bool nv04_fifo_cache_flush(struct drm_device *); +extern bool nv04_fifo_cache_pull(struct drm_device *, bool); extern int nv04_fifo_channel_id(struct drm_device *); extern int nv04_fifo_create_context(struct nouveau_channel *); extern void nv04_fifo_destroy_context(struct nouveau_channel *); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index e76ec2d207a..9f988431f34 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -76,6 +76,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.cache_flush = nv04_fifo_cache_flush; + engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv04_fifo_channel_id; engine->fifo.create_context = nv04_fifo_create_context; engine->fifo.destroy_context = nv04_fifo_destroy_context; @@ -115,6 +117,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.cache_flush = nv04_fifo_cache_flush; + engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.destroy_context = nv10_fifo_destroy_context; @@ -154,6 +158,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.cache_flush = nv04_fifo_cache_flush; + engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.destroy_context = nv10_fifo_destroy_context; @@ -193,6 +199,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.cache_flush = nv04_fifo_cache_flush; + engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.destroy_context = nv10_fifo_destroy_context; @@ -233,6 +241,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.cache_flush = nv04_fifo_cache_flush; + engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv40_fifo_create_context; engine->fifo.destroy_context = nv40_fifo_destroy_context; diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c index 0c3cd53c731..f31347b8c9b 100644 --- a/drivers/gpu/drm/nouveau/nv04_fifo.c +++ b/drivers/gpu/drm/nouveau/nv04_fifo.c @@ -71,6 +71,40 @@ nv04_fifo_reassign(struct drm_device *dev, bool enable) return (reassign == 1); } +bool +nv04_fifo_cache_flush(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; + uint64_t start = ptimer->read(dev); + + do { + if (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) == + nv_rd32(dev, NV03_PFIFO_CACHE1_PUT)) + return true; + + } while (ptimer->read(dev) - start < 100000000); + + NV_ERROR(dev, "Timeout flushing the PFIFO cache.\n"); + + return false; +} + +bool +nv04_fifo_cache_pull(struct drm_device *dev, bool enable) +{ + uint32_t pull = nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0); + + if (enable) { + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull | 1); + } else { + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull & ~1); + nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); + } + + return !!(pull & 1); +} + int nv04_fifo_channel_id(struct drm_device *dev) { -- cgit v1.2.3-70-g09d2 From cb00f7c1419d09ee0daf7d8bed86f253d98db7b4 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 16 Dec 2009 12:12:27 +0100 Subject: drm/nouveau: Pre-G80 tiling support. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_drv.h | 18 +++++ drivers/gpu/drm/nouveau/nouveau_reg.h | 16 ++--- drivers/gpu/drm/nouveau/nouveau_state.c | 8 +++ drivers/gpu/drm/nouveau/nv10_fb.c | 32 +++++++-- drivers/gpu/drm/nouveau/nv10_graph.c | 28 +++++--- drivers/gpu/drm/nouveau/nv20_graph.c | 61 ++++++++--------- drivers/gpu/drm/nouveau/nv40_fb.c | 53 +++++++++------ drivers/gpu/drm/nouveau/nv40_graph.c | 116 +++++++++++++------------------- 8 files changed, 185 insertions(+), 147 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 48d0ad9434a..446a92ad2ee 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -277,8 +277,13 @@ struct nouveau_timer_engine { }; struct nouveau_fb_engine { + int num_tiles; + int (*init)(struct drm_device *dev); void (*takedown)(struct drm_device *dev); + + void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch); }; struct nouveau_fifo_engine { @@ -332,6 +337,9 @@ struct nouveau_pgraph_engine { void (*destroy_context)(struct nouveau_channel *); int (*load_context)(struct nouveau_channel *); int (*unload_context)(struct drm_device *); + + void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch); }; struct nouveau_engine { @@ -881,10 +889,14 @@ extern void nv04_fb_takedown(struct drm_device *); /* nv10_fb.c */ extern int nv10_fb_init(struct drm_device *); extern void nv10_fb_takedown(struct drm_device *); +extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t, + uint32_t, uint32_t); /* nv40_fb.c */ extern int nv40_fb_init(struct drm_device *); extern void nv40_fb_takedown(struct drm_device *); +extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, + uint32_t, uint32_t); /* nv04_fifo.c */ extern int nv04_fifo_init(struct drm_device *); @@ -945,6 +957,8 @@ extern void nv10_graph_destroy_context(struct nouveau_channel *); extern int nv10_graph_load_context(struct nouveau_channel *); extern int nv10_graph_unload_context(struct drm_device *); extern void nv10_graph_context_switch(struct drm_device *); +extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t, + uint32_t, uint32_t); /* nv20_graph.c */ extern struct nouveau_pgraph_object_class nv20_graph_grclass[]; @@ -956,6 +970,8 @@ extern int nv20_graph_unload_context(struct drm_device *); extern int nv20_graph_init(struct drm_device *); extern void nv20_graph_takedown(struct drm_device *); extern int nv30_graph_init(struct drm_device *); +extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t, + uint32_t, uint32_t); /* nv40_graph.c */ extern struct nouveau_pgraph_object_class nv40_graph_grclass[]; @@ -967,6 +983,8 @@ extern void nv40_graph_destroy_context(struct nouveau_channel *); extern int nv40_graph_load_context(struct nouveau_channel *); extern int nv40_graph_unload_context(struct drm_device *); extern void nv40_grctx_init(struct nouveau_grctx *); +extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t, + uint32_t, uint32_t); /* nv50_graph.c */ extern struct nouveau_pgraph_object_class nv50_graph_grclass[]; diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h index fa1b0e7165b..251f1b3b38b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_reg.h +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h @@ -349,19 +349,19 @@ #define NV04_PGRAPH_BLEND 0x00400824 #define NV04_PGRAPH_STORED_FMT 0x00400830 #define NV04_PGRAPH_PATT_COLORRAM 0x00400900 -#define NV40_PGRAPH_TILE0(i) (0x00400900 + (i*16)) -#define NV40_PGRAPH_TLIMIT0(i) (0x00400904 + (i*16)) -#define NV40_PGRAPH_TSIZE0(i) (0x00400908 + (i*16)) -#define NV40_PGRAPH_TSTATUS0(i) (0x0040090C + (i*16)) +#define NV20_PGRAPH_TILE(i) (0x00400900 + (i*16)) +#define NV20_PGRAPH_TLIMIT(i) (0x00400904 + (i*16)) +#define NV20_PGRAPH_TSIZE(i) (0x00400908 + (i*16)) +#define NV20_PGRAPH_TSTATUS(i) (0x0040090C + (i*16)) #define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16)) #define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16)) #define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16)) #define NV10_PGRAPH_TSTATUS(i) (0x00400B0C + (i*16)) #define NV04_PGRAPH_U_RAM 0x00400D00 -#define NV47_PGRAPH_TILE0(i) (0x00400D00 + (i*16)) -#define NV47_PGRAPH_TLIMIT0(i) (0x00400D04 + (i*16)) -#define NV47_PGRAPH_TSIZE0(i) (0x00400D08 + (i*16)) -#define NV47_PGRAPH_TSTATUS0(i) (0x00400D0C + (i*16)) +#define NV47_PGRAPH_TILE(i) (0x00400D00 + (i*16)) +#define NV47_PGRAPH_TLIMIT(i) (0x00400D04 + (i*16)) +#define NV47_PGRAPH_TSIZE(i) (0x00400D08 + (i*16)) +#define NV47_PGRAPH_TSTATUS(i) (0x00400D0C + (i*16)) #define NV04_PGRAPH_V_RAM 0x00400D40 #define NV04_PGRAPH_W_RAM 0x00400D80 #define NV10_PGRAPH_COMBINER0_IN_ALPHA 0x00400E40 diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 9f988431f34..6a459139910 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -102,6 +102,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv10_fb_init; engine->fb.takedown = nv10_fb_takedown; + engine->fb.set_region_tiling = nv10_fb_set_region_tiling; engine->graph.grclass = nv10_graph_grclass; engine->graph.init = nv10_graph_init; engine->graph.takedown = nv10_graph_takedown; @@ -111,6 +112,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.fifo_access = nv04_graph_fifo_access; engine->graph.load_context = nv10_graph_load_context; engine->graph.unload_context = nv10_graph_unload_context; + engine->graph.set_region_tiling = nv10_graph_set_region_tiling; engine->fifo.channels = 32; engine->fifo.init = nv10_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; @@ -143,6 +145,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv10_fb_init; engine->fb.takedown = nv10_fb_takedown; + engine->fb.set_region_tiling = nv10_fb_set_region_tiling; engine->graph.grclass = nv20_graph_grclass; engine->graph.init = nv20_graph_init; engine->graph.takedown = nv20_graph_takedown; @@ -152,6 +155,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.fifo_access = nv04_graph_fifo_access; engine->graph.load_context = nv20_graph_load_context; engine->graph.unload_context = nv20_graph_unload_context; + engine->graph.set_region_tiling = nv20_graph_set_region_tiling; engine->fifo.channels = 32; engine->fifo.init = nv10_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; @@ -184,6 +188,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv10_fb_init; engine->fb.takedown = nv10_fb_takedown; + engine->fb.set_region_tiling = nv10_fb_set_region_tiling; engine->graph.grclass = nv30_graph_grclass; engine->graph.init = nv30_graph_init; engine->graph.takedown = nv20_graph_takedown; @@ -193,6 +198,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.destroy_context = nv20_graph_destroy_context; engine->graph.load_context = nv20_graph_load_context; engine->graph.unload_context = nv20_graph_unload_context; + engine->graph.set_region_tiling = nv20_graph_set_region_tiling; engine->fifo.channels = 32; engine->fifo.init = nv10_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; @@ -226,6 +232,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv40_fb_init; engine->fb.takedown = nv40_fb_takedown; + engine->fb.set_region_tiling = nv40_fb_set_region_tiling; engine->graph.grclass = nv40_graph_grclass; engine->graph.init = nv40_graph_init; engine->graph.takedown = nv40_graph_takedown; @@ -235,6 +242,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.destroy_context = nv40_graph_destroy_context; engine->graph.load_context = nv40_graph_load_context; engine->graph.unload_context = nv40_graph_unload_context; + engine->graph.set_region_tiling = nv40_graph_set_region_tiling; engine->fifo.channels = 32; engine->fifo.init = nv40_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; diff --git a/drivers/gpu/drm/nouveau/nv10_fb.c b/drivers/gpu/drm/nouveau/nv10_fb.c index 79e2d104d70..cc5cda44e50 100644 --- a/drivers/gpu/drm/nouveau/nv10_fb.c +++ b/drivers/gpu/drm/nouveau/nv10_fb.c @@ -3,17 +3,37 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" +void +nv10_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t limit = max(1u, addr + size) - 1; + + if (pitch) { + if (dev_priv->card_type >= NV_20) + addr |= 1; + else + addr |= 1 << 31; + } + + nv_wr32(dev, NV10_PFB_TLIMIT(i), limit); + nv_wr32(dev, NV10_PFB_TSIZE(i), pitch); + nv_wr32(dev, NV10_PFB_TILE(i), addr); +} + int nv10_fb_init(struct drm_device *dev) { - uint32_t fb_bar_size; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; int i; - fb_bar_size = drm_get_resource_len(dev, 0) - 1; - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { - nv_wr32(dev, NV10_PFB_TILE(i), 0); - nv_wr32(dev, NV10_PFB_TLIMIT(i), fb_bar_size); - } + pfb->num_tiles = NV10_PFB_TILE__SIZE; + + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->num_tiles; i++) + pfb->set_region_tiling(dev, i, 0, 0, 0); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c index 6870e0ee2e7..fcf2cdd1949 100644 --- a/drivers/gpu/drm/nouveau/nv10_graph.c +++ b/drivers/gpu/drm/nouveau/nv10_graph.c @@ -807,6 +807,20 @@ void nv10_graph_destroy_context(struct nouveau_channel *chan) chan->pgraph_ctx = NULL; } +void +nv10_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + uint32_t limit = max(1u, addr + size) - 1; + + if (pitch) + addr |= 1 << 31; + + nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), limit); + nv_wr32(dev, NV10_PGRAPH_TSIZE(i), pitch); + nv_wr32(dev, NV10_PGRAPH_TILE(i), addr); +} + int nv10_graph_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -838,17 +852,9 @@ int nv10_graph_init(struct drm_device *dev) } else nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); - /* copy tile info from PFB */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { - nv_wr32(dev, NV10_PGRAPH_TILE(i), - nv_rd32(dev, NV10_PFB_TILE(i))); - nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), - nv_rd32(dev, NV10_PFB_TLIMIT(i))); - nv_wr32(dev, NV10_PGRAPH_TSIZE(i), - nv_rd32(dev, NV10_PFB_TSIZE(i))); - nv_wr32(dev, NV10_PGRAPH_TSTATUS(i), - nv_rd32(dev, NV10_PFB_TSTATUS(i))); - } + /* Turn all the tiling regions off. */ + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) + nv10_graph_set_region_tiling(dev, i, 0, 0, 0); nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH1, 0x00000000); nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH2, 0x00000000); diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c index 18ba74f1970..d6fc0a82f03 100644 --- a/drivers/gpu/drm/nouveau/nv20_graph.c +++ b/drivers/gpu/drm/nouveau/nv20_graph.c @@ -514,6 +514,27 @@ nv20_graph_rdi(struct drm_device *dev) nouveau_wait_for_idle(dev); } +void +nv20_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + uint32_t limit = max(1u, addr + size) - 1; + + if (pitch) + addr |= 1; + + nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); + nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); + nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); + + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, limit); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, pitch); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, addr); +} + int nv20_graph_init(struct drm_device *dev) { @@ -572,27 +593,10 @@ nv20_graph_init(struct drm_device *dev) nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030); } - /* copy tile info from PFB */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { - nv_wr32(dev, 0x00400904 + i * 0x10, - nv_rd32(dev, NV10_PFB_TLIMIT(i))); - /* which is NV40_PGRAPH_TLIMIT0(i) ?? */ - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + i * 4); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, - nv_rd32(dev, NV10_PFB_TLIMIT(i))); - nv_wr32(dev, 0x00400908 + i * 0x10, - nv_rd32(dev, NV10_PFB_TSIZE(i))); - /* which is NV40_PGRAPH_TSIZE0(i) ?? */ - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + i * 4); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, - nv_rd32(dev, NV10_PFB_TSIZE(i))); - nv_wr32(dev, 0x00400900 + i * 0x10, - nv_rd32(dev, NV10_PFB_TILE(i))); - /* which is NV40_PGRAPH_TILE0(i) ?? */ - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + i * 4); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, - nv_rd32(dev, NV10_PFB_TILE(i))); - } + /* Turn all the tiling regions off. */ + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) + nv20_graph_set_region_tiling(dev, i, 0, 0, 0); + for (i = 0; i < 8; i++) { nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4)); nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4); @@ -704,18 +708,9 @@ nv30_graph_init(struct drm_device *dev) nv_wr32(dev, 0x4000c0, 0x00000016); - /* copy tile info from PFB */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { - nv_wr32(dev, 0x00400904 + i * 0x10, - nv_rd32(dev, NV10_PFB_TLIMIT(i))); - /* which is NV40_PGRAPH_TLIMIT0(i) ?? */ - nv_wr32(dev, 0x00400908 + i * 0x10, - nv_rd32(dev, NV10_PFB_TSIZE(i))); - /* which is NV40_PGRAPH_TSIZE0(i) ?? */ - nv_wr32(dev, 0x00400900 + i * 0x10, - nv_rd32(dev, NV10_PFB_TILE(i))); - /* which is NV40_PGRAPH_TILE0(i) ?? */ - } + /* Turn all the tiling regions off. */ + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) + nv20_graph_set_region_tiling(dev, i, 0, 0, 0); nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c index ca1d27107a8..3cd07d8d5bd 100644 --- a/drivers/gpu/drm/nouveau/nv40_fb.c +++ b/drivers/gpu/drm/nouveau/nv40_fb.c @@ -3,12 +3,37 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" +void +nv40_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t limit = max(1u, addr + size) - 1; + + if (pitch) + addr |= 1; + + switch (dev_priv->chipset) { + case 0x40: + nv_wr32(dev, NV10_PFB_TLIMIT(i), limit); + nv_wr32(dev, NV10_PFB_TSIZE(i), pitch); + nv_wr32(dev, NV10_PFB_TILE(i), addr); + break; + + default: + nv_wr32(dev, NV40_PFB_TLIMIT(i), limit); + nv_wr32(dev, NV40_PFB_TSIZE(i), pitch); + nv_wr32(dev, NV40_PFB_TILE(i), addr); + break; + } +} + int nv40_fb_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t fb_bar_size, tmp; - int num_tiles; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + uint32_t tmp; int i; /* This is strictly a NV4x register (don't know about NV5x). */ @@ -23,35 +48,23 @@ nv40_fb_init(struct drm_device *dev) case 0x45: tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2); nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15)); - num_tiles = NV10_PFB_TILE__SIZE; + pfb->num_tiles = NV10_PFB_TILE__SIZE; break; case 0x46: /* G72 */ case 0x47: /* G70 */ case 0x49: /* G71 */ case 0x4b: /* G73 */ case 0x4c: /* C51 (G7X version) */ - num_tiles = NV40_PFB_TILE__SIZE_1; + pfb->num_tiles = NV40_PFB_TILE__SIZE_1; break; default: - num_tiles = NV40_PFB_TILE__SIZE_0; + pfb->num_tiles = NV40_PFB_TILE__SIZE_0; break; } - fb_bar_size = drm_get_resource_len(dev, 0) - 1; - switch (dev_priv->chipset) { - case 0x40: - for (i = 0; i < num_tiles; i++) { - nv_wr32(dev, NV10_PFB_TILE(i), 0); - nv_wr32(dev, NV10_PFB_TLIMIT(i), fb_bar_size); - } - break; - default: - for (i = 0; i < num_tiles; i++) { - nv_wr32(dev, NV40_PFB_TILE(i), 0); - nv_wr32(dev, NV40_PFB_TLIMIT(i), fb_bar_size); - } - break; - } + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->num_tiles; i++) + pfb->set_region_tiling(dev, i, 0, 0, 0); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index 2b332bb55ac..53e8afe1dcd 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c @@ -181,6 +181,48 @@ nv40_graph_unload_context(struct drm_device *dev) return ret; } +void +nv40_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t limit = max(1u, addr + size) - 1; + + if (pitch) + addr |= 1; + + switch (dev_priv->chipset) { + case 0x44: + case 0x4a: + case 0x4e: + nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); + nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); + nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); + break; + + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + nv_wr32(dev, NV47_PGRAPH_TSIZE(i), pitch); + nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), limit); + nv_wr32(dev, NV47_PGRAPH_TILE(i), addr); + nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch); + nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit); + nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr); + break; + + default: + nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); + nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); + nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); + nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch); + nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit); + nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr); + break; + } +} + /* * G70 0x47 * G71 0x49 @@ -195,7 +237,8 @@ nv40_graph_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = (struct drm_nouveau_private *)dev->dev_private; - uint32_t vramsz, tmp; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + uint32_t vramsz; int i, j; nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & @@ -292,74 +335,9 @@ nv40_graph_init(struct drm_device *dev) nv_wr32(dev, 0x400b38, 0x2ffff800); nv_wr32(dev, 0x400b3c, 0x00006000); - /* copy tile info from PFB */ - switch (dev_priv->chipset) { - case 0x40: /* vanilla NV40 */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { - tmp = nv_rd32(dev, NV10_PFB_TILE(i)); - nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp); - tmp = nv_rd32(dev, NV10_PFB_TLIMIT(i)); - nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp); - tmp = nv_rd32(dev, NV10_PFB_TSIZE(i)); - nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp); - tmp = nv_rd32(dev, NV10_PFB_TSTATUS(i)); - nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp); - } - break; - case 0x44: - case 0x4a: - case 0x4e: /* NV44-based cores don't have 0x406900? */ - for (i = 0; i < NV40_PFB_TILE__SIZE_0; i++) { - tmp = nv_rd32(dev, NV40_PFB_TILE(i)); - nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i)); - nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSIZE(i)); - nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i)); - nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp); - } - break; - case 0x46: - case 0x47: - case 0x49: - case 0x4b: /* G7X-based cores */ - for (i = 0; i < NV40_PFB_TILE__SIZE_1; i++) { - tmp = nv_rd32(dev, NV40_PFB_TILE(i)); - nv_wr32(dev, NV47_PGRAPH_TILE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i)); - nv_wr32(dev, NV47_PGRAPH_TLIMIT0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSIZE(i)); - nv_wr32(dev, NV47_PGRAPH_TSIZE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i)); - nv_wr32(dev, NV47_PGRAPH_TSTATUS0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp); - } - break; - default: /* everything else */ - for (i = 0; i < NV40_PFB_TILE__SIZE_0; i++) { - tmp = nv_rd32(dev, NV40_PFB_TILE(i)); - nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i)); - nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSIZE(i)); - nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i)); - nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp); - } - break; - } + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->num_tiles; i++) + nv40_graph_set_region_tiling(dev, i, 0, 0, 0); /* begin RAM config */ vramsz = drm_get_resource_len(dev, 0) - 1; -- cgit v1.2.3-70-g09d2 From a0af9add499cf29a16707b7b148842992077f4cb Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Fri, 11 Dec 2009 16:51:09 +0100 Subject: drm/nouveau: Make the MM aware of pre-G80 tiling. This commit has also the following 3 bugfix commits squashed into it from the nouveau git tree: drm/nouveau: Fix up the tiling alignment restrictions for nv1x. drm/nouveau: Fix up the nv2x tiling alignment restrictions. drm/nv50: fix align typo for g9x Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_bo.c | 221 ++++++++++++++++++++++++---------- drivers/gpu/drm/nouveau/nouveau_drv.h | 22 ++++ drivers/gpu/drm/nouveau/nouveau_mem.c | 87 +++++++++++++ 3 files changed, 265 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 0cad6d834eb..1d6036fabd5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -37,6 +37,7 @@ static void nouveau_bo_del_ttm(struct ttm_buffer_object *bo) { struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct drm_device *dev = dev_priv->dev; struct nouveau_bo *nvbo = nouveau_bo(bo); ttm_bo_kunmap(&nvbo->kmap); @@ -44,12 +45,83 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) if (unlikely(nvbo->gem)) DRM_ERROR("bo %p still attached to GEM object\n", bo); + if (nvbo->tile) + nv10_mem_expire_tiling(dev, nvbo->tile, NULL); + spin_lock(&dev_priv->ttm.bo_list_lock); list_del(&nvbo->head); spin_unlock(&dev_priv->ttm.bo_list_lock); kfree(nvbo); } +static void +nouveau_bo_fixup_align(struct drm_device *dev, + uint32_t tile_mode, uint32_t tile_flags, + int *align, int *size) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* + * Some of the tile_flags have a periodic structure of N*4096 bytes, + * align to to that as well as the page size. Overallocate memory to + * avoid corruption of other buffer objects. + */ + if (dev_priv->card_type == NV_50) { + switch (tile_flags) { + case 0x1800: + case 0x2800: + case 0x4800: + case 0x7a00: + if (dev_priv->chipset >= 0xA0) { + /* This is based on high end cards with 448 bits + * memory bus, could be different elsewhere.*/ + *size += 6 * 28672; + /* 8 * 28672 is the actual alignment requirement + * but we must also align to page size. */ + *align = 2 * 8 * 28672; + } else if (dev_priv->chipset >= 0x90) { + *size += 3 * 16384; + *align = 12 * 16384; + } else { + *size += 3 * 8192; + /* 12 * 8192 is the actual alignment requirement + * but we must also align to page size. */ + *align = 2 * 12 * 8192; + } + break; + default: + break; + } + + } else { + if (tile_mode) { + if (dev_priv->chipset >= 0x40) { + *align = 65536; + *size = roundup(*size, 64 * tile_mode); + + } else if (dev_priv->chipset >= 0x30) { + *align = 32768; + *size = roundup(*size, 64 * tile_mode); + + } else if (dev_priv->chipset >= 0x20) { + *align = 16384; + *size = roundup(*size, 64 * tile_mode); + + } else if (dev_priv->chipset >= 0x10) { + *align = 16384; + *size = roundup(*size, 32 * tile_mode); + } + } + } + + *size = ALIGN(*size, PAGE_SIZE); + + if (dev_priv->card_type == NV_50) { + *size = ALIGN(*size, 65536); + *align = max(65536, *align); + } +} + int nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, int size, int align, uint32_t flags, uint32_t tile_mode, @@ -70,46 +142,9 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, nvbo->tile_mode = tile_mode; nvbo->tile_flags = tile_flags; - /* - * Some of the tile_flags have a periodic structure of N*4096 bytes, - * align to to that as well as the page size. Overallocate memory to - * avoid corruption of other buffer objects. - */ - switch (tile_flags) { - case 0x1800: - case 0x2800: - case 0x4800: - case 0x7a00: - if (dev_priv->chipset >= 0xA0) { - /* This is based on high end cards with 448 bits - * memory bus, could be different elsewhere.*/ - size += 6 * 28672; - /* 8 * 28672 is the actual alignment requirement, - * but we must also align to page size. */ - align = 2 * 8 * 28672; - } else if (dev_priv->chipset >= 0x90) { - size += 3 * 16384; - align = 12 * 16834; - } else { - size += 3 * 8192; - /* 12 * 8192 is the actual alignment requirement, - * but we must also align to page size. */ - align = 2 * 12 * 8192; - } - break; - default: - break; - } - + nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size); align >>= PAGE_SHIFT; - size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); - if (dev_priv->card_type == NV_50) { - size = (size + 65535) & ~65535; - if (align < (65536 / PAGE_SIZE)) - align = (65536 / PAGE_SIZE); - } - if (flags & TTM_PL_FLAG_VRAM) nvbo->placements[n++] = TTM_PL_FLAG_VRAM | TTM_PL_MASK_CACHING; if (flags & TTM_PL_FLAG_TT) @@ -421,6 +456,7 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) /* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access * TTM_PL_{VRAM,TT} directly. */ + static int nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, struct nouveau_bo *nvbo, bool evict, bool no_wait, @@ -455,11 +491,12 @@ nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan, } static int -nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, int no_wait, - struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) +nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, + int no_wait, struct ttm_mem_reg *new_mem) { struct nouveau_bo *nvbo = nouveau_bo(bo); struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct ttm_mem_reg *old_mem = &bo->mem; struct nouveau_channel *chan; uint64_t src_offset, dst_offset; uint32_t page_count; @@ -559,7 +596,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, if (ret) goto out; - ret = nouveau_bo_move_m2mf(bo, true, no_wait, &bo->mem, &tmp_mem); + ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait, &tmp_mem); if (ret) goto out; @@ -597,7 +634,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, if (ret) goto out; - ret = nouveau_bo_move_m2mf(bo, true, no_wait, &bo->mem, new_mem); + ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait, new_mem); if (ret) goto out; @@ -612,52 +649,106 @@ out: } static int -nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, - bool no_wait, struct ttm_mem_reg *new_mem) +nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, + struct nouveau_tile_reg **new_tile) { struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - struct nouveau_bo *nvbo = nouveau_bo(bo); struct drm_device *dev = dev_priv->dev; - struct ttm_mem_reg *old_mem = &bo->mem; + struct nouveau_bo *nvbo = nouveau_bo(bo); + uint64_t offset; int ret; - if (dev_priv->card_type == NV_50 && new_mem->mem_type == TTM_PL_VRAM && - !nvbo->no_vm) { - uint64_t offset = new_mem->mm_node->start << PAGE_SHIFT; + if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) { + /* Nothing to do. */ + *new_tile = NULL; + return 0; + } + + offset = new_mem->mm_node->start << PAGE_SHIFT; + if (dev_priv->card_type == NV_50) { ret = nv50_mem_vm_bind_linear(dev, offset + dev_priv->vm_vram_base, new_mem->size, nvbo->tile_flags, offset); if (ret) return ret; + + } else if (dev_priv->card_type >= NV_10) { + *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, + nvbo->tile_mode); } + return 0; +} + +static void +nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, + struct nouveau_tile_reg *new_tile, + struct nouveau_tile_reg **old_tile) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct drm_device *dev = dev_priv->dev; + + if (dev_priv->card_type >= NV_10 && + dev_priv->card_type < NV_50) { + if (*old_tile) + nv10_mem_expire_tiling(dev, *old_tile, bo->sync_obj); + + *old_tile = new_tile; + } +} + +static int +nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, + bool no_wait, struct ttm_mem_reg *new_mem) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct nouveau_bo *nvbo = nouveau_bo(bo); + struct ttm_mem_reg *old_mem = &bo->mem; + struct nouveau_tile_reg *new_tile = NULL; + int ret = 0; + + ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile); + if (ret) + return ret; + + /* Software copy if the card isn't up and running yet. */ if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE || - !dev_priv->channel) - return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + !dev_priv->channel) { + ret = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + goto out; + } + /* Fake bo copy. */ if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { BUG_ON(bo->mem.mm_node != NULL); bo->mem = *new_mem; new_mem->mm_node = NULL; - return 0; + goto out; } - if (new_mem->mem_type == TTM_PL_SYSTEM) { - if (old_mem->mem_type == TTM_PL_SYSTEM) - return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); - if (nouveau_bo_move_flipd(bo, evict, intr, no_wait, new_mem)) - return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } else if (old_mem->mem_type == TTM_PL_SYSTEM) { - if (nouveau_bo_move_flips(bo, evict, intr, no_wait, new_mem)) - return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } else { - if (nouveau_bo_move_m2mf(bo, evict, no_wait, old_mem, new_mem)) - return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } + /* Hardware assisted copy. */ + if (new_mem->mem_type == TTM_PL_SYSTEM) + ret = nouveau_bo_move_flipd(bo, evict, intr, no_wait, new_mem); + else if (old_mem->mem_type == TTM_PL_SYSTEM) + ret = nouveau_bo_move_flips(bo, evict, intr, no_wait, new_mem); + else + ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait, new_mem); - return 0; + if (!ret) + goto out; + + /* Fallback to software copy. */ + ret = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + +out: + if (ret) + nouveau_bo_vm_cleanup(bo, NULL, &new_tile); + else + nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile); + + return ret; } static int diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 446a92ad2ee..9c9815bf505 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -59,11 +59,19 @@ struct nouveau_grctx; #define MAX_NUM_DCB_ENTRIES 16 #define NOUVEAU_MAX_CHANNEL_NR 128 +#define NOUVEAU_MAX_TILE_NR 15 #define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL) #define NV50_VM_BLOCK (512*1024*1024ULL) #define NV50_VM_VRAM_NR (NV50_VM_MAX_VRAM / NV50_VM_BLOCK) +struct nouveau_tile_reg { + struct nouveau_fence *fence; + uint32_t addr; + uint32_t size; + bool used; +}; + struct nouveau_bo { struct ttm_buffer_object bo; struct ttm_placement placement; @@ -83,6 +91,7 @@ struct nouveau_bo { uint32_t tile_mode; uint32_t tile_flags; + struct nouveau_tile_reg *tile; struct drm_gem_object *gem; struct drm_file *cpu_filp; @@ -558,6 +567,12 @@ struct drm_nouveau_private { unsigned long sg_handle; } gart_info; + /* nv10-nv40 tiling regions */ + struct { + struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR]; + spinlock_t lock; + } tile; + /* G8x/G9x virtual address space */ uint64_t vm_gart_base; uint64_t vm_gart_size; @@ -695,6 +710,13 @@ extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap); extern int nouveau_mem_init(struct drm_device *); extern int nouveau_mem_init_agp(struct drm_device *); extern void nouveau_mem_close(struct drm_device *); +extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev, + uint32_t addr, + uint32_t size, + uint32_t pitch); +extern void nv10_mem_expire_tiling(struct drm_device *dev, + struct nouveau_tile_reg *tile, + struct nouveau_fence *fence); extern int nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt, uint32_t size, uint32_t flags, uint64_t phys); diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 5158a12f784..fb9bdd6edf1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -191,6 +191,92 @@ void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap) } } +/* + * NV10-NV40 tiling helpers + */ + +static void +nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + tile->addr = addr; + tile->size = size; + tile->used = !!pitch; + nouveau_fence_unref((void **)&tile->fence); + + if (!pfifo->cache_flush(dev)) + return; + + pfifo->reassign(dev, false); + pfifo->cache_flush(dev); + pfifo->cache_pull(dev, false); + + nouveau_wait_for_idle(dev); + + pgraph->set_region_tiling(dev, i, addr, size, pitch); + pfb->set_region_tiling(dev, i, addr, size, pitch); + + pfifo->cache_pull(dev, true); + pfifo->reassign(dev, true); +} + +struct nouveau_tile_reg * +nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, + uint32_t pitch) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nouveau_tile_reg *tile = dev_priv->tile.reg, *found = NULL; + int i; + + spin_lock(&dev_priv->tile.lock); + + for (i = 0; i < pfb->num_tiles; i++) { + if (tile[i].used) + /* Tile region in use. */ + continue; + + if (tile[i].fence && + !nouveau_fence_signalled(tile[i].fence, NULL)) + /* Pending tile region. */ + continue; + + if (max(tile[i].addr, addr) < + min(tile[i].addr + tile[i].size, addr + size)) + /* Kill an intersecting tile region. */ + nv10_mem_set_region_tiling(dev, i, 0, 0, 0); + + if (pitch && !found) { + /* Free tile region. */ + nv10_mem_set_region_tiling(dev, i, addr, size, pitch); + found = &tile[i]; + } + } + + spin_unlock(&dev_priv->tile.lock); + + return found; +} + +void +nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile, + struct nouveau_fence *fence) +{ + if (fence) { + /* Mark it as pending. */ + tile->fence = fence; + nouveau_fence_ref(fence); + } + + tile->used = false; +} + /* * NV50 VM helpers */ @@ -513,6 +599,7 @@ nouveau_mem_init(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->ttm.bo_list); spin_lock_init(&dev_priv->ttm.bo_list_lock); + spin_lock_init(&dev_priv->tile.lock); dev_priv->fb_available_size = nouveau_mem_fb_amount(dev); -- cgit v1.2.3-70-g09d2 From cea7789f2a680893e812776dd7202dd50475f9d2 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 16 Dec 2009 12:27:11 +0100 Subject: drm/i2c/ch7006: Drop build time dependency to nouveau. This partially reverts e4b41066, as this driver is intended to be useful with any KMS driver for suitable hardware. The missing build dependency that commit workarounded was DRM_KMS_HELPER. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index b1bc1ea182b..1175429da10 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -30,12 +30,11 @@ config DRM_NOUVEAU_DEBUG via debugfs. menu "I2C encoder or helper chips" - depends on DRM && I2C + depends on DRM && DRM_KMS_HELPER && I2C config DRM_I2C_CH7006 tristate "Chrontel ch7006 TV encoder" - depends on DRM_NOUVEAU - default m + default m if DRM_NOUVEAU help Support for Chrontel ch7006 and similar TV encoders, found on some nVidia video cards. -- cgit v1.2.3-70-g09d2 From 77e2b5ed83864f0a58e2cd046b15aab6865babfb Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 16 Dec 2009 19:05:00 +0100 Subject: drm/nouveau: Fix "general protection fault" in the flipd/flips eviction path. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_bo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 1d6036fabd5..365fc650817 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -584,7 +584,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, placement.fpfn = placement.lpfn = 0; placement.num_placement = placement.num_busy_placement = 1; - placement.placement = &placement_memtype; + placement.placement = placement.busy_placement = &placement_memtype; tmp_mem = *new_mem; tmp_mem.mm_node = NULL; @@ -622,7 +622,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, placement.fpfn = placement.lpfn = 0; placement.num_placement = placement.num_busy_placement = 1; - placement.placement = &placement_memtype; + placement.placement = placement.busy_placement = &placement_memtype; tmp_mem = *new_mem; tmp_mem.mm_node = NULL; -- cgit v1.2.3-70-g09d2 From 27f691a69d411b9b2093163cdd27780f9c927422 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 16 Dec 2009 19:05:38 +0100 Subject: drm/nouveau: No need to force evict=true when swapping evicted BOs back in. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 365fc650817..73af53fe75a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -634,7 +634,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, if (ret) goto out; - ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait, new_mem); + ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait, new_mem); if (ret) goto out; -- cgit v1.2.3-70-g09d2 From 8dea4a1935fabbc5fcea6016d6670e6bc06de198 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 16 Dec 2009 19:03:28 +0100 Subject: drm/nouveau: Drop redundant placement initialization. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_bo.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 73af53fe75a..5fd462f4940 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -130,7 +130,7 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_bo *nvbo; - int ret, n = 0; + int ret = 0; nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); if (!nvbo) @@ -145,19 +145,11 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size); align >>= PAGE_SHIFT; - if (flags & TTM_PL_FLAG_VRAM) - nvbo->placements[n++] = TTM_PL_FLAG_VRAM | TTM_PL_MASK_CACHING; - if (flags & TTM_PL_FLAG_TT) - nvbo->placements[n++] = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; nvbo->placement.fpfn = 0; nvbo->placement.lpfn = mappable ? dev_priv->fb_mappable_pages : 0; - nvbo->placement.placement = nvbo->placements; - nvbo->placement.busy_placement = nvbo->placements; - nvbo->placement.num_placement = n; - nvbo->placement.num_busy_placement = n; + nouveau_bo_placement_set(nvbo, flags); nvbo->channel = chan; - nouveau_bo_placement_set(nvbo, flags); ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size, ttm_bo_type_device, &nvbo->placement, align, 0, false, NULL, size, nouveau_bo_del_ttm); -- cgit v1.2.3-70-g09d2 From 75c722d7ea70b791d179ec900e7c88bd6d5fd71e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 21 Dec 2009 12:16:52 +1000 Subject: drm/nv50: ignore vbios table's claim to the contrary if EDID says >8bpc Should fix dim panel issues reported on Dell M6400/M6500. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_display.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index a9263d92a23..90f0bf59fbc 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -690,9 +690,21 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent, int pxclk) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_connector *nv_connector = NULL; + struct drm_encoder *encoder; struct nvbios *bios = &dev_priv->VBIOS; uint32_t mc, script = 0, or; + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + if (nv_encoder->dcb != dcbent) + continue; + + nv_connector = nouveau_encoder_connector_get(nv_encoder); + break; + } + or = ffs(dcbent->or) - 1; mc = nv50_display_mode_ctrl(dev, dcbent->type != OUTPUT_ANALOG, or); switch (dcbent->type) { @@ -711,6 +723,11 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent, } else if (bios->fp.strapless_is_24bit & 1) script |= 0x0200; + + if (nv_connector && nv_connector->edid && + (nv_connector->edid->revision >= 4) && + (nv_connector->edid->input & 0x70) >= 0x20) + script |= 0x0200; } if (nouveau_uscript_lvds >= 0) { -- cgit v1.2.3-70-g09d2 From 3033f14d6538e0e7c3c53d3ed1ff6cec28260b98 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 21 Dec 2009 23:00:41 +0100 Subject: drm/nv50: fix fillrect color struct fb_fillrect->color is not a color, but index into pseudo_palette array Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_fbcon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index 6bcc6d39e9b..c966ef83485 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -10,6 +10,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) struct drm_device *dev = par->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; + uint32_t color = ((uint32_t *) info->pseudo_palette)[rect->color]; if (info->state != FBINFO_STATE_RUNNING) return; @@ -31,7 +32,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) OUT_RING(chan, 1); } BEGIN_RING(chan, NvSub2D, 0x0588, 1); - OUT_RING(chan, rect->color); + OUT_RING(chan, color); BEGIN_RING(chan, NvSub2D, 0x0600, 4); OUT_RING(chan, rect->dx); OUT_RING(chan, rect->dy); -- cgit v1.2.3-70-g09d2 From 11d6eb2af53395b25e1d6b8b79bb9a999c3e4c4d Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 17 Dec 2009 18:52:44 +0100 Subject: drm/nouveau: Clean up the nv17-nv4x load detection code a bit. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_drv.h | 6 +----- drivers/gpu/drm/nouveau/nv04_dac.c | 35 +++++++++++++++++++---------------- drivers/gpu/drm/nouveau/nv17_tv.c | 27 +++++++++++++++++---------- 3 files changed, 37 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 9c9815bf505..7da88a92c83 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1074,8 +1074,7 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, /* nv04_dac.c */ extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry); -extern enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, - struct drm_connector *connector); +extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder); extern int nv04_dac_output_offset(struct drm_encoder *encoder); extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); @@ -1093,9 +1092,6 @@ extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry); /* nv17_tv.c */ extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry); -extern enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, - struct drm_connector *connector, - uint32_t pin_mask); /* nv04_display.c */ extern int nv04_display_create(struct drm_device *); diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index d9f32879ba3..d0e038d2894 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -212,16 +212,15 @@ out: return connector_status_disconnected; } -enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, - struct drm_connector *connector) +uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; - uint32_t testval, regoffset = nv04_dac_output_offset(encoder); + uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, saved_rtest_ctrl, saved_gpio0, saved_gpio1, temp, routput; - int head, present = 0; + int head; #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) if (dcb->type == OUTPUT_TV) { @@ -287,13 +286,7 @@ enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, temp | NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED); msleep(5); - temp = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); - - if (dcb->type == OUTPUT_TV) - present = (nv17_tv_detect(encoder, connector, temp) - == connector_status_connected); - else - present = temp & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI; + sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL); NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL, @@ -310,15 +303,25 @@ enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); - if (present) { - NV_INFO(dev, "Load detected on output %c\n", '@' + ffs(dcb->or)); + return sample; +} + +static enum drm_connector_status +nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + uint32_t sample = nv17_dac_sample_load(encoder); + + if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { + NV_INFO(dev, "Load detected on output %c\n", + '@' + ffs(dcb->or)); return connector_status_connected; + } else { + return connector_status_disconnected; } - - return connector_status_disconnected; } - static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 81c01353a9f..5fa4242e4c7 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c @@ -33,13 +33,15 @@ #include "nouveau_hw.h" #include "nv17_tv.h" -enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, - struct drm_connector *connector, - uint32_t pin_mask) +static enum drm_connector_status +nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) { + struct drm_device *dev = encoder->dev; + struct drm_mode_config *conf = &dev->mode_config; struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); + struct dcb_entry *dcb = tv_enc->base.dcb; - tv_enc->pin_mask = pin_mask >> 28 & 0xe; + tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe; switch (tv_enc->pin_mask) { case 0x2: @@ -50,7 +52,7 @@ enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO; break; case 0xe: - if (nouveau_encoder(encoder)->dcb->tvconf.has_component_output) + if (dcb->tvconf.has_component_output) tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Component; else tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SCART; @@ -61,11 +63,16 @@ enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, } drm_connector_property_set_value(connector, - encoder->dev->mode_config.tv_subconnector_property, - tv_enc->subconnector); + conf->tv_subconnector_property, + tv_enc->subconnector); - return tv_enc->subconnector ? connector_status_connected : - connector_status_disconnected; + if (tv_enc->subconnector) { + NV_INFO(dev, "Load detected on output %c\n", + '@' + ffs(dcb->or)); + return connector_status_connected; + } else { + return connector_status_disconnected; + } } static const struct { @@ -633,7 +640,7 @@ static struct drm_encoder_helper_funcs nv17_tv_helper_funcs = { .prepare = nv17_tv_prepare, .commit = nv17_tv_commit, .mode_set = nv17_tv_mode_set, - .detect = nv17_dac_detect, + .detect = nv17_tv_detect, }; static struct drm_encoder_slave_funcs nv17_tv_slave_funcs = { -- cgit v1.2.3-70-g09d2 From 0829168b474663d8b13f6105368dbbf4a1a03256 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 17 Dec 2009 18:57:44 +0100 Subject: drm/nouveau: Implement nv42-nv43 TV load detection. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nv17_tv.c | 90 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 5fa4242e4c7..58b917c3341 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c @@ -33,15 +33,103 @@ #include "nouveau_hw.h" #include "nv17_tv.h" +static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t testval, regoffset = nv04_dac_output_offset(encoder); + uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, + fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; + uint32_t sample = 0; + int head; + +#define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) + testval = RGB_TEST_DATA(0x82, 0xeb, 0x82); + if (dev_priv->vbios->tvdactestval) + testval = dev_priv->vbios->tvdactestval; + + dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); + head = (dacclk & 0x100) >> 8; + + /* Save the previous state. */ + gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1); + gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0); + fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); + fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); + fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); + fp_control = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL); + test_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); + ctv_1c = NVReadRAMDAC(dev, head, 0x680c1c); + ctv_14 = NVReadRAMDAC(dev, head, 0x680c14); + ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); + + /* Prepare the DAC for load detection. */ + nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true); + nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true); + + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, 1183); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, + NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | + NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12 | + NV_PRAMDAC_FP_TG_CONTROL_READ_PROG | + NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | + NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS); + + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, 0); + + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, + (dacclk & ~0xff) | 0x22); + msleep(1); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, + (dacclk & ~0xff) | 0x21); + + NVWriteRAMDAC(dev, head, 0x680c1c, 1 << 20); + NVWriteRAMDAC(dev, head, 0x680c14, 4 << 16); + + /* Sample pin 0x4 (usually S-video luma). */ + NVWriteRAMDAC(dev, head, 0x680c6c, testval >> 10 & 0x3ff); + msleep(20); + sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset) + & 0x4 << 28; + + /* Sample the remaining pins. */ + NVWriteRAMDAC(dev, head, 0x680c6c, testval & 0x3ff); + msleep(20); + sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset) + & 0xa << 28; + + /* Restore the previous state. */ + NVWriteRAMDAC(dev, head, 0x680c1c, ctv_1c); + NVWriteRAMDAC(dev, head, 0x680c14, ctv_14); + NVWriteRAMDAC(dev, head, 0x680c6c, ctv_6c); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, dacclk); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, test_ctrl); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, fp_control); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); + nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1); + nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0); + + return sample; +} + static enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_mode_config *conf = &dev->mode_config; struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); struct dcb_entry *dcb = tv_enc->base.dcb; - tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe; + if (dev_priv->chipset == 0x42 || + dev_priv->chipset == 0x43) + tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe; + else + tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe; switch (tv_enc->pin_mask) { case 0x2: -- cgit v1.2.3-70-g09d2 From 111b459af191891f49682f21e11f348703cd8bdd Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Tue, 22 Dec 2009 18:24:09 +0100 Subject: drm/nouveau: Don't skip card take down on nv0x. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_state.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 6a459139910..a6b573e8982 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -722,8 +722,8 @@ static void nouveau_close(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - /* In the case of an error dev_priv may not be be allocated yet */ - if (dev_priv && dev_priv->card_type) + /* In the case of an error dev_priv may not be allocated yet */ + if (dev_priv) nouveau_card_takedown(dev); } -- cgit v1.2.3-70-g09d2 From 1c7059e4f36e76c72cefbb6c9bd2bcf45c12e777 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 25 Dec 2009 18:51:17 +0100 Subject: drm/nouveau: better alignment of bo sizes and use roundup instead of ALIGN - Aligning to block size should ensure that the extra size is enough. - Using roundup, because not all sizes are powers of two. Signed-off-by: Maarten Maathuis --- drivers/gpu/drm/nouveau/nouveau_bo.c | 8 ++++++-- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 5fd462f4940..a0c9e00e706 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -73,6 +73,7 @@ nouveau_bo_fixup_align(struct drm_device *dev, case 0x4800: case 0x7a00: if (dev_priv->chipset >= 0xA0) { + *size = roundup(*size, 28672); /* This is based on high end cards with 448 bits * memory bus, could be different elsewhere.*/ *size += 6 * 28672; @@ -80,9 +81,11 @@ nouveau_bo_fixup_align(struct drm_device *dev, * but we must also align to page size. */ *align = 2 * 8 * 28672; } else if (dev_priv->chipset >= 0x90) { + *size = roundup(*size, 16384); *size += 3 * 16384; *align = 12 * 16384; } else { + *size = roundup(*size, 8192); *size += 3 * 8192; /* 12 * 8192 is the actual alignment requirement * but we must also align to page size. */ @@ -114,10 +117,11 @@ nouveau_bo_fixup_align(struct drm_device *dev, } } - *size = ALIGN(*size, PAGE_SIZE); + /* ALIGN works only on powers of two. */ + *size = roundup(*size, PAGE_SIZE); if (dev_priv->card_type == NV_50) { - *size = ALIGN(*size, 65536); + *size = roundup(*size, 65536); *align = max(65536, *align); } } diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 84af25c238b..44cbbeeb774 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -212,11 +212,11 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, mode_cmd.bpp = surface_bpp; mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3); - mode_cmd.pitch = ALIGN(mode_cmd.pitch, 256); + mode_cmd.pitch = roundup(mode_cmd.pitch, 256); mode_cmd.depth = surface_depth; size = mode_cmd.pitch * mode_cmd.height; - size = ALIGN(size, PAGE_SIZE); + size = roundup(size, PAGE_SIZE); ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, false, true, &nvbo); -- cgit v1.2.3-70-g09d2 From a510604df9444a2a1bdecafc048749e0f35816b5 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sat, 26 Dec 2009 21:46:36 +0100 Subject: drm/nv50: make the blocksize depend on vram size - This should be better than what we have now. - I'm less sure about the non power of two path. Signed-off-by: Maarten Maathuis --- drivers/gpu/drm/nouveau/nouveau_bo.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index a0c9e00e706..e342a418d43 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -33,6 +33,8 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" +#include + static void nouveau_bo_del_ttm(struct ttm_buffer_object *bo) { @@ -67,29 +69,29 @@ nouveau_bo_fixup_align(struct drm_device *dev, * avoid corruption of other buffer objects. */ if (dev_priv->card_type == NV_50) { + uint32_t block_size = nouveau_mem_fb_amount(dev) >> 15; + int i; + switch (tile_flags) { case 0x1800: case 0x2800: case 0x4800: case 0x7a00: - if (dev_priv->chipset >= 0xA0) { - *size = roundup(*size, 28672); - /* This is based on high end cards with 448 bits - * memory bus, could be different elsewhere.*/ - *size += 6 * 28672; - /* 8 * 28672 is the actual alignment requirement - * but we must also align to page size. */ - *align = 2 * 8 * 28672; - } else if (dev_priv->chipset >= 0x90) { - *size = roundup(*size, 16384); - *size += 3 * 16384; - *align = 12 * 16384; + *size = roundup(*size, block_size); + if (is_power_of_2(block_size)) { + *size += 3 * block_size; + for (i = 1; i < 10; i++) { + *align = 12 * i * block_size; + if (!(*align % 65536)) + break; + } } else { - *size = roundup(*size, 8192); - *size += 3 * 8192; - /* 12 * 8192 is the actual alignment requirement - * but we must also align to page size. */ - *align = 2 * 12 * 8192; + *size += 6 * block_size; + for (i = 1; i < 10; i++) { + *align = 8 * i * block_size; + if (!(*align % 65536)) + break; + } } break; default: -- cgit v1.2.3-70-g09d2 From f03a314b4671407c4ff69a2d85e72413e8064c48 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sat, 26 Dec 2009 02:42:45 +0100 Subject: drm/nouveau: Allocate a per-channel instance of NV_SW. It will be useful for various synchronization purposes, mostly stolen from "[PATCH] drm/nv50: synchronize user channel after buffer object move on kernel channel" by Maarten Maathuis. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_channel.c | 4 +++- drivers/gpu/drm/nouveau/nouveau_dma.c | 17 +++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_dma.h | 10 ++++++---- drivers/gpu/drm/nouveau/nouveau_drv.h | 20 +++++++++++--------- drivers/gpu/drm/nouveau/nouveau_object.c | 2 +- drivers/gpu/drm/nouveau/nv04_fbcon.c | 19 ++++++++++--------- 6 files changed, 48 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 9aaa972f882..4f378b68fe7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -414,7 +414,9 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, init->subchan[0].grclass = 0x0039; else init->subchan[0].grclass = 0x5039; - init->nr_subchan = 1; + init->subchan[1].handle = NvSw; + init->subchan[1].grclass = NV_SW; + init->nr_subchan = 2; /* Named memory object area */ ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index 703553687b2..f1fd3f2b981 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -35,6 +35,7 @@ nouveau_dma_init(struct nouveau_channel *chan) struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *m2mf = NULL; + struct nouveau_gpuobj *nvsw = NULL; int ret, i; /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ @@ -47,6 +48,15 @@ nouveau_dma_init(struct nouveau_channel *chan) if (ret) return ret; + /* Create an NV_SW object for various sync purposes */ + ret = nouveau_gpuobj_sw_new(chan, NV_SW, &nvsw); + if (ret) + return ret; + + ret = nouveau_gpuobj_ref_add(dev, chan, NvSw, nvsw, NULL); + if (ret) + return ret; + /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */ ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy); if (ret) @@ -87,6 +97,13 @@ nouveau_dma_init(struct nouveau_channel *chan) BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); OUT_RING(chan, NvNotify0); + /* Initialise NV_SW */ + ret = RING_SPACE(chan, 2); + if (ret) + return ret; + BEGIN_RING(chan, NvSubSw, 0, 1); + OUT_RING(chan, NvSw); + /* Sit back and pray the channel works.. */ FIRE_RING(chan); diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h index 04e85d8f757..dabfd655f93 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.h +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h @@ -46,10 +46,11 @@ /* Hardcoded object assignments to subchannels (subchannel id). */ enum { NvSubM2MF = 0, - NvSub2D = 1, - NvSubCtxSurf2D = 1, - NvSubGdiRect = 2, - NvSubImageBlit = 3 + NvSubSw = 1, + NvSub2D = 2, + NvSubCtxSurf2D = 2, + NvSubGdiRect = 3, + NvSubImageBlit = 4 }; /* Object handles. */ @@ -67,6 +68,7 @@ enum { NvClipRect = 0x8000000b, NvGdiRect = 0x8000000c, NvImageBlit = 0x8000000d, + NvSw = 0x8000000e, /* G80+ display objects */ NvEvoVRAM = 0x01000000, diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 7da88a92c83..9181eaefe91 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -788,6 +788,8 @@ extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *, uint32_t *o_ret); extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, struct nouveau_gpuobj **); +extern int nouveau_gpuobj_sw_new(struct nouveau_channel *, int class, + struct nouveau_gpuobj **); extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, struct drm_file *); extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, @@ -1330,14 +1332,14 @@ nv_two_reg_pll(struct drm_device *dev) return false; } -#define NV50_NVSW 0x0000506e -#define NV50_NVSW_DMA_SEMAPHORE 0x00000060 -#define NV50_NVSW_SEMAPHORE_OFFSET 0x00000064 -#define NV50_NVSW_SEMAPHORE_ACQUIRE 0x00000068 -#define NV50_NVSW_SEMAPHORE_RELEASE 0x0000006c -#define NV50_NVSW_DMA_VBLSEM 0x0000018c -#define NV50_NVSW_VBLSEM_OFFSET 0x00000400 -#define NV50_NVSW_VBLSEM_RELEASE_VALUE 0x00000404 -#define NV50_NVSW_VBLSEM_RELEASE 0x00000408 +#define NV_SW 0x0000506e +#define NV_SW_DMA_SEMAPHORE 0x00000060 +#define NV_SW_SEMAPHORE_OFFSET 0x00000064 +#define NV_SW_SEMAPHORE_ACQUIRE 0x00000068 +#define NV_SW_SEMAPHORE_RELEASE 0x0000006c +#define NV_SW_DMA_VBLSEM 0x0000018c +#define NV_SW_VBLSEM_OFFSET 0x00000400 +#define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 +#define NV_SW_VBLSEM_RELEASE 0x00000408 #endif /* __NOUVEAU_DRV_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index 93379bb81be..6c2cf81716d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c @@ -881,7 +881,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, return 0; } -static int +int nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, struct nouveau_gpuobj **gpuobj_ret) { diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index 09a31071ee5..d2d7f0838dc 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -184,6 +184,7 @@ nv04_fbcon_accel_init(struct fb_info *info) struct drm_device *dev = par->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; + const int sub = NvSubCtxSurf2D; int surface_fmt, pattern_fmt, rect_fmt; int ret; @@ -247,25 +248,25 @@ nv04_fbcon_accel_init(struct fb_info *info) return 0; } - BEGIN_RING(chan, 1, 0x0000, 1); + BEGIN_RING(chan, sub, 0x0000, 1); OUT_RING(chan, NvCtxSurf2D); - BEGIN_RING(chan, 1, 0x0184, 2); + BEGIN_RING(chan, sub, 0x0184, 2); OUT_RING(chan, NvDmaFB); OUT_RING(chan, NvDmaFB); - BEGIN_RING(chan, 1, 0x0300, 4); + BEGIN_RING(chan, sub, 0x0300, 4); OUT_RING(chan, surface_fmt); OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16)); OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); - BEGIN_RING(chan, 1, 0x0000, 1); + BEGIN_RING(chan, sub, 0x0000, 1); OUT_RING(chan, NvRop); - BEGIN_RING(chan, 1, 0x0300, 1); + BEGIN_RING(chan, sub, 0x0300, 1); OUT_RING(chan, 0x55); - BEGIN_RING(chan, 1, 0x0000, 1); + BEGIN_RING(chan, sub, 0x0000, 1); OUT_RING(chan, NvImagePatt); - BEGIN_RING(chan, 1, 0x0300, 8); + BEGIN_RING(chan, sub, 0x0300, 8); OUT_RING(chan, pattern_fmt); #ifdef __BIG_ENDIAN OUT_RING(chan, 2); @@ -279,9 +280,9 @@ nv04_fbcon_accel_init(struct fb_info *info) OUT_RING(chan, ~0); OUT_RING(chan, ~0); - BEGIN_RING(chan, 1, 0x0000, 1); + BEGIN_RING(chan, sub, 0x0000, 1); OUT_RING(chan, NvClipRect); - BEGIN_RING(chan, 1, 0x0300, 2); + BEGIN_RING(chan, sub, 0x0300, 2); OUT_RING(chan, 0); OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual); -- cgit v1.2.3-70-g09d2 From 8c032ce73ef3a9e5a14c35ea3de19f1b9a8d7c0d Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sat, 26 Dec 2009 02:09:36 +0100 Subject: drm/nouveau: Use the software object for fencing. This should avoid a race condition on nv0x, if we're doing it with actual PGRAPH objects and a there's a fence within the FIFO DMA fetch area when a context switch kicks in. In that case we get an ILLEGAL_MTHD interrupt as expected, but the values in PGRAPH_TRAPPED_ADDR aren't calculated correctly and they're almost useless (e.g. you can see ILLEGAL_MTHDs for the now inactive channel, with a wrong offset/data pair). Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_fence.c | 2 +- drivers/gpu/drm/nouveau/nv04_graph.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index dacac9a0842..faddf53ff9e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -142,7 +142,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) list_add_tail(&fence->entry, &chan->fence.pending); spin_unlock_irqrestore(&chan->fence.lock, flags); - BEGIN_RING(chan, NvSubM2MF, USE_REFCNT ? 0x0050 : 0x0150, 1); + BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1); OUT_RING(chan, fence->sequence); FIRE_RING(chan); diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c index d561d773c0f..82c77f9d469 100644 --- a/drivers/gpu/drm/nouveau/nv04_graph.c +++ b/drivers/gpu/drm/nouveau/nv04_graph.c @@ -547,7 +547,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, return 0; } -static struct nouveau_pgraph_object_method nv04_graph_mthds_m2mf[] = { +static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = { { 0x0150, nv04_graph_mthd_set_ref }, {} }; @@ -558,7 +558,7 @@ static struct nouveau_pgraph_object_method nv04_graph_mthds_set_operation[] = { }; struct nouveau_pgraph_object_class nv04_graph_grclass[] = { - { 0x0039, false, nv04_graph_mthds_m2mf }, + { 0x0039, false, NULL }, { 0x004a, false, nv04_graph_mthds_set_operation }, /* gdirect */ { 0x005f, false, nv04_graph_mthds_set_operation }, /* imageblit */ { 0x0061, false, nv04_graph_mthds_set_operation }, /* ifc */ @@ -574,6 +574,7 @@ struct nouveau_pgraph_object_class nv04_graph_grclass[] = { { 0x0053, false, NULL }, /* surf3d */ { 0x0054, false, NULL }, /* tex_tri */ { 0x0055, false, NULL }, /* multitex_tri */ + { 0x506e, true, nv04_graph_mthds_sw }, {} }; -- cgit v1.2.3-70-g09d2 From be9721a951bd5ee6346dd2f3eed8a6fd1761c186 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sat, 26 Dec 2009 14:39:46 +0100 Subject: drm/nv04: Context switching fixes. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nv04_graph.c | 152 ++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c index 82c77f9d469..98f3b40318d 100644 --- a/drivers/gpu/drm/nouveau/nv04_graph.c +++ b/drivers/gpu/drm/nouveau/nv04_graph.c @@ -28,6 +28,10 @@ #include "nouveau_drv.h" static uint32_t nv04_graph_ctx_regs[] = { + 0x0040053c, + 0x00400544, + 0x00400540, + 0x00400548, NV04_PGRAPH_CTX_SWITCH1, NV04_PGRAPH_CTX_SWITCH2, NV04_PGRAPH_CTX_SWITCH3, @@ -102,69 +106,69 @@ static uint32_t nv04_graph_ctx_regs[] = { NV04_PGRAPH_PATT_COLOR0, NV04_PGRAPH_PATT_COLOR1, NV04_PGRAPH_PATT_COLORRAM+0x00, - NV04_PGRAPH_PATT_COLORRAM+0x01, - NV04_PGRAPH_PATT_COLORRAM+0x02, - NV04_PGRAPH_PATT_COLORRAM+0x03, NV04_PGRAPH_PATT_COLORRAM+0x04, - NV04_PGRAPH_PATT_COLORRAM+0x05, - NV04_PGRAPH_PATT_COLORRAM+0x06, - NV04_PGRAPH_PATT_COLORRAM+0x07, NV04_PGRAPH_PATT_COLORRAM+0x08, - NV04_PGRAPH_PATT_COLORRAM+0x09, - NV04_PGRAPH_PATT_COLORRAM+0x0A, - NV04_PGRAPH_PATT_COLORRAM+0x0B, - NV04_PGRAPH_PATT_COLORRAM+0x0C, - NV04_PGRAPH_PATT_COLORRAM+0x0D, - NV04_PGRAPH_PATT_COLORRAM+0x0E, - NV04_PGRAPH_PATT_COLORRAM+0x0F, + NV04_PGRAPH_PATT_COLORRAM+0x0c, NV04_PGRAPH_PATT_COLORRAM+0x10, - NV04_PGRAPH_PATT_COLORRAM+0x11, - NV04_PGRAPH_PATT_COLORRAM+0x12, - NV04_PGRAPH_PATT_COLORRAM+0x13, NV04_PGRAPH_PATT_COLORRAM+0x14, - NV04_PGRAPH_PATT_COLORRAM+0x15, - NV04_PGRAPH_PATT_COLORRAM+0x16, - NV04_PGRAPH_PATT_COLORRAM+0x17, NV04_PGRAPH_PATT_COLORRAM+0x18, - NV04_PGRAPH_PATT_COLORRAM+0x19, - NV04_PGRAPH_PATT_COLORRAM+0x1A, - NV04_PGRAPH_PATT_COLORRAM+0x1B, - NV04_PGRAPH_PATT_COLORRAM+0x1C, - NV04_PGRAPH_PATT_COLORRAM+0x1D, - NV04_PGRAPH_PATT_COLORRAM+0x1E, - NV04_PGRAPH_PATT_COLORRAM+0x1F, + NV04_PGRAPH_PATT_COLORRAM+0x1c, NV04_PGRAPH_PATT_COLORRAM+0x20, - NV04_PGRAPH_PATT_COLORRAM+0x21, - NV04_PGRAPH_PATT_COLORRAM+0x22, - NV04_PGRAPH_PATT_COLORRAM+0x23, NV04_PGRAPH_PATT_COLORRAM+0x24, - NV04_PGRAPH_PATT_COLORRAM+0x25, - NV04_PGRAPH_PATT_COLORRAM+0x26, - NV04_PGRAPH_PATT_COLORRAM+0x27, NV04_PGRAPH_PATT_COLORRAM+0x28, - NV04_PGRAPH_PATT_COLORRAM+0x29, - NV04_PGRAPH_PATT_COLORRAM+0x2A, - NV04_PGRAPH_PATT_COLORRAM+0x2B, - NV04_PGRAPH_PATT_COLORRAM+0x2C, - NV04_PGRAPH_PATT_COLORRAM+0x2D, - NV04_PGRAPH_PATT_COLORRAM+0x2E, - NV04_PGRAPH_PATT_COLORRAM+0x2F, + NV04_PGRAPH_PATT_COLORRAM+0x2c, NV04_PGRAPH_PATT_COLORRAM+0x30, - NV04_PGRAPH_PATT_COLORRAM+0x31, - NV04_PGRAPH_PATT_COLORRAM+0x32, - NV04_PGRAPH_PATT_COLORRAM+0x33, NV04_PGRAPH_PATT_COLORRAM+0x34, - NV04_PGRAPH_PATT_COLORRAM+0x35, - NV04_PGRAPH_PATT_COLORRAM+0x36, - NV04_PGRAPH_PATT_COLORRAM+0x37, NV04_PGRAPH_PATT_COLORRAM+0x38, - NV04_PGRAPH_PATT_COLORRAM+0x39, - NV04_PGRAPH_PATT_COLORRAM+0x3A, - NV04_PGRAPH_PATT_COLORRAM+0x3B, - NV04_PGRAPH_PATT_COLORRAM+0x3C, - NV04_PGRAPH_PATT_COLORRAM+0x3D, - NV04_PGRAPH_PATT_COLORRAM+0x3E, - NV04_PGRAPH_PATT_COLORRAM+0x3F, + NV04_PGRAPH_PATT_COLORRAM+0x3c, + NV04_PGRAPH_PATT_COLORRAM+0x40, + NV04_PGRAPH_PATT_COLORRAM+0x44, + NV04_PGRAPH_PATT_COLORRAM+0x48, + NV04_PGRAPH_PATT_COLORRAM+0x4c, + NV04_PGRAPH_PATT_COLORRAM+0x50, + NV04_PGRAPH_PATT_COLORRAM+0x54, + NV04_PGRAPH_PATT_COLORRAM+0x58, + NV04_PGRAPH_PATT_COLORRAM+0x5c, + NV04_PGRAPH_PATT_COLORRAM+0x60, + NV04_PGRAPH_PATT_COLORRAM+0x64, + NV04_PGRAPH_PATT_COLORRAM+0x68, + NV04_PGRAPH_PATT_COLORRAM+0x6c, + NV04_PGRAPH_PATT_COLORRAM+0x70, + NV04_PGRAPH_PATT_COLORRAM+0x74, + NV04_PGRAPH_PATT_COLORRAM+0x78, + NV04_PGRAPH_PATT_COLORRAM+0x7c, + NV04_PGRAPH_PATT_COLORRAM+0x80, + NV04_PGRAPH_PATT_COLORRAM+0x84, + NV04_PGRAPH_PATT_COLORRAM+0x88, + NV04_PGRAPH_PATT_COLORRAM+0x8c, + NV04_PGRAPH_PATT_COLORRAM+0x90, + NV04_PGRAPH_PATT_COLORRAM+0x94, + NV04_PGRAPH_PATT_COLORRAM+0x98, + NV04_PGRAPH_PATT_COLORRAM+0x9c, + NV04_PGRAPH_PATT_COLORRAM+0xa0, + NV04_PGRAPH_PATT_COLORRAM+0xa4, + NV04_PGRAPH_PATT_COLORRAM+0xa8, + NV04_PGRAPH_PATT_COLORRAM+0xac, + NV04_PGRAPH_PATT_COLORRAM+0xb0, + NV04_PGRAPH_PATT_COLORRAM+0xb4, + NV04_PGRAPH_PATT_COLORRAM+0xb8, + NV04_PGRAPH_PATT_COLORRAM+0xbc, + NV04_PGRAPH_PATT_COLORRAM+0xc0, + NV04_PGRAPH_PATT_COLORRAM+0xc4, + NV04_PGRAPH_PATT_COLORRAM+0xc8, + NV04_PGRAPH_PATT_COLORRAM+0xcc, + NV04_PGRAPH_PATT_COLORRAM+0xd0, + NV04_PGRAPH_PATT_COLORRAM+0xd4, + NV04_PGRAPH_PATT_COLORRAM+0xd8, + NV04_PGRAPH_PATT_COLORRAM+0xdc, + NV04_PGRAPH_PATT_COLORRAM+0xe0, + NV04_PGRAPH_PATT_COLORRAM+0xe4, + NV04_PGRAPH_PATT_COLORRAM+0xe8, + NV04_PGRAPH_PATT_COLORRAM+0xec, + NV04_PGRAPH_PATT_COLORRAM+0xf0, + NV04_PGRAPH_PATT_COLORRAM+0xf4, + NV04_PGRAPH_PATT_COLORRAM+0xf8, + NV04_PGRAPH_PATT_COLORRAM+0xfc, NV04_PGRAPH_PATTERN, 0x0040080c, NV04_PGRAPH_PATTERN_SHAPE, @@ -247,14 +251,6 @@ static uint32_t nv04_graph_ctx_regs[] = { 0x004004f8, 0x0040047c, 0x004004fc, - 0x0040053c, - 0x00400544, - 0x00400540, - 0x00400548, - 0x00400560, - 0x00400568, - 0x00400564, - 0x0040056c, 0x00400534, 0x00400538, 0x00400514, @@ -341,9 +337,8 @@ static uint32_t nv04_graph_ctx_regs[] = { 0x00400500, 0x00400504, NV04_PGRAPH_VALID1, - NV04_PGRAPH_VALID2 - - + NV04_PGRAPH_VALID2, + NV04_PGRAPH_DEBUG_3 }; struct graph_state { @@ -388,6 +383,18 @@ nv04_graph_context_switch(struct drm_device *dev) pgraph->fifo_access(dev, true); } +static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) { + if (nv04_graph_ctx_regs[i] == reg) + return &ctx->nv04[i]; + } + + return NULL; +} + int nv04_graph_create_context(struct nouveau_channel *chan) { struct graph_state *pgraph_ctx; @@ -398,15 +405,8 @@ int nv04_graph_create_context(struct nouveau_channel *chan) if (pgraph_ctx == NULL) return -ENOMEM; - /* dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; */ - pgraph_ctx->nv04[0] = 0x0001ffff; - /* is it really needed ??? */ -#if 0 - dev_priv->fifos[channel].pgraph_ctx[1] = - nv_rd32(dev, NV_PGRAPH_DEBUG_4); - dev_priv->fifos[channel].pgraph_ctx[2] = - nv_rd32(dev, 0x004006b0); -#endif + *ctx_reg(pgraph_ctx, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31; + return 0; } @@ -429,9 +429,13 @@ int nv04_graph_load_context(struct nouveau_channel *chan) nv_wr32(dev, nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]); nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10010100); - nv_wr32(dev, NV04_PGRAPH_CTX_USER, chan->id << 24); + + tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; + nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp | chan->id << 24); + tmp = nv_rd32(dev, NV04_PGRAPH_FFINTFC_ST2); nv_wr32(dev, NV04_PGRAPH_FFINTFC_ST2, tmp & 0x000fffff); + return 0; } @@ -494,7 +498,7 @@ int nv04_graph_init(struct drm_device *dev) nv_wr32(dev, NV04_PGRAPH_STATE , 0xFFFFFFFF); nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL , 0x10000100); tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= dev_priv->engine.fifo.channels << 24; + tmp |= (dev_priv->engine.fifo.channels - 1) << 24; nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp); /* These don't belong here, they're part of a per-channel context */ -- cgit v1.2.3-70-g09d2 From bf5302b9496b25fe80ffa8a4fd191ad95c217864 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 4 Jan 2010 09:10:55 +1000 Subject: drm/nouveau: fix handling of fbcon colours in 8bpp Depending on the visual, the colours handed to us in fillrect() can either be an actual colour, or an index into the pseudo-palette. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv04_fbcon.c | 7 +++++-- drivers/gpu/drm/nouveau/nv50_fbcon.c | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index d2d7f0838dc..bd08a0dc984 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -62,7 +62,6 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) struct drm_device *dev = par->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; - uint32_t color = ((uint32_t *) info->pseudo_palette)[rect->color]; if (info->state != FBINFO_STATE_RUNNING) return; @@ -80,7 +79,11 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1); OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3); BEGIN_RING(chan, NvSubGdiRect, 0x03fc, 1); - OUT_RING(chan, color); + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) + OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]); + else + OUT_RING(chan, rect->color); BEGIN_RING(chan, NvSubGdiRect, 0x0400, 2); OUT_RING(chan, (rect->dx << 16) | rect->dy); OUT_RING(chan, (rect->width << 16) | rect->height); diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index c966ef83485..cc34356ab0b 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -10,7 +10,6 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) struct drm_device *dev = par->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; - uint32_t color = ((uint32_t *) info->pseudo_palette)[rect->color]; if (info->state != FBINFO_STATE_RUNNING) return; @@ -32,7 +31,11 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) OUT_RING(chan, 1); } BEGIN_RING(chan, NvSub2D, 0x0588, 1); - OUT_RING(chan, color); + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) + OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]); + else + OUT_RING(chan, rect->color); BEGIN_RING(chan, NvSub2D, 0x0600, 4); OUT_RING(chan, rect->dx); OUT_RING(chan, rect->dy); -- cgit v1.2.3-70-g09d2 From 61768bf1e694056cb41029b60e1270bf2578a83f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 4 Jan 2010 12:53:01 +1000 Subject: drm/nouveau: remove unused nouveau_channel_idle() function Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_channel.c | 41 ------------------------------- drivers/gpu/drm/nouveau/nouveau_drv.h | 1 - 2 files changed, 42 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 4f378b68fe7..d1c7f8c911c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -235,47 +235,6 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, return 0; } -int -nouveau_channel_idle(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; - uint32_t caches; - int idle; - - if (!chan) { - NV_ERROR(dev, "no channel...\n"); - return 1; - } - - caches = nv_rd32(dev, NV03_PFIFO_CACHES); - nv_wr32(dev, NV03_PFIFO_CACHES, caches & ~1); - - if (engine->fifo.channel_id(dev) != chan->id) { - struct nouveau_gpuobj *ramfc = - chan->ramfc ? chan->ramfc->gpuobj : NULL; - - if (!ramfc) { - NV_ERROR(dev, "No RAMFC for channel %d\n", chan->id); - return 1; - } - - engine->instmem.prepare_access(dev, false); - if (nv_ro32(dev, ramfc, 0) != nv_ro32(dev, ramfc, 1)) - idle = 0; - else - idle = 1; - engine->instmem.finish_access(dev); - } else { - idle = (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET) == - nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); - } - - nv_wr32(dev, NV03_PFIFO_CACHES, caches); - return idle; -} - /* stops a fifo */ void nouveau_channel_free(struct nouveau_channel *chan) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 9181eaefe91..4087a9a20ba 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -745,7 +745,6 @@ extern int nouveau_channel_alloc(struct drm_device *dev, struct drm_file *file_priv, uint32_t fb_ctxdma, uint32_t tt_ctxdma); extern void nouveau_channel_free(struct nouveau_channel *); -extern int nouveau_channel_idle(struct nouveau_channel *chan); /* nouveau_object.c */ extern int nouveau_gpuobj_early_init(struct drm_device *); -- cgit v1.2.3-70-g09d2 From 846975a97b098bbbf1232a01a3a5723a4bddd9e7 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 4 Jan 2010 19:25:09 +0100 Subject: drm/nouveau: create function for "dealing" with gpu lockup It's mostly a cleanup, but in nv50_fbcon_accel_init gpu lockup message was printed, but HWACCEL_DISBALED flag was not set. Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 15 +++++++++++---- drivers/gpu/drm/nouveau/nouveau_fbcon.h | 1 + drivers/gpu/drm/nouveau/nv04_fbcon.c | 15 +++++---------- drivers/gpu/drm/nouveau/nv50_fbcon.c | 17 +++++------------ 4 files changed, 22 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 44cbbeeb774..0b05c869e0e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -64,8 +64,7 @@ nouveau_fbcon_sync(struct fb_info *info) return 0; if (RING_SPACE(chan, 4)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); return 0; } @@ -86,8 +85,7 @@ nouveau_fbcon_sync(struct fb_info *info) } if (ret) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); return 0; } @@ -380,3 +378,12 @@ nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb) return 0; } + +void nouveau_fbcon_gpu_lockup(struct fb_info *info) +{ + struct nouveau_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h index 8531140fedb..462e0b87b4b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h @@ -43,5 +43,6 @@ void nouveau_fbcon_zfill(struct drm_device *dev); int nv04_fbcon_accel_init(struct fb_info *info); int nv50_fbcon_accel_init(struct fb_info *info); +void nouveau_fbcon_gpu_lockup(struct fb_info *info); #endif /* __NV50_FBCON_H__ */ diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index bd08a0dc984..d910873c136 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -39,8 +39,7 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) return; if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -67,8 +66,7 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) return; if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -112,8 +110,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) } if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -147,8 +144,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) int iter_len = dsize > 128 ? 128 : dsize; if (RING_SPACE(chan, iter_len + 1)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); cfb_imageblit(info, image); return; } @@ -246,8 +242,7 @@ nv04_fbcon_accel_init(struct fb_info *info) return ret; if (RING_SPACE(chan, 49)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index cc34356ab0b..e4f279ee61c 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -16,9 +16,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -60,9 +58,7 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) return; if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -105,8 +101,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) } if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -139,9 +134,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) int push = dwords > 2047 ? 2047 : dwords; if (RING_SPACE(chan, push + 1)) { - NV_ERROR(dev, - "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); cfb_imageblit(info, image); return; } @@ -203,7 +196,7 @@ nv50_fbcon_accel_init(struct fb_info *info) ret = RING_SPACE(chan, 59); if (ret) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + nouveau_fbcon_gpu_lockup(info); return ret; } -- cgit v1.2.3-70-g09d2 From 7fb8ec8e2bedc8381243cf4bdc4cfa8e657397a8 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 5 Jan 2010 09:41:05 +1000 Subject: drm/nv50: restore correct cache1 get/put address on fifoctx load Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_fifo.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index b7282284f08..39caf167587 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c @@ -384,8 +384,8 @@ nv50_fifo_load_context(struct nouveau_channel *chan) nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr), nv_ro32(dev, cache, (ptr * 2) + 1)); } - nv_wr32(dev, 0x3210, cnt << 2); - nv_wr32(dev, 0x3270, 0); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, cnt << 2); + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); /* guessing that all the 0x34xx regs aren't on NV50 */ if (!IS_G80) { @@ -398,8 +398,6 @@ nv50_fifo_load_context(struct nouveau_channel *chan) dev_priv->engine.instmem.finish_access(dev); - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); return 0; } -- cgit v1.2.3-70-g09d2 From bbb8c3d8820893694a3567716adb3b6f6ba2b7d0 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 4 Jan 2010 15:52:20 +1000 Subject: drm/nouveau: have ttm's fault handler called directly There's no good reason for us to have our own anymore, this is left over from an early port to these TTM interfaces. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_ttm.c | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 187eb84e4da..c385d50f041 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -28,45 +28,17 @@ #include "nouveau_drv.h" -static struct vm_operations_struct nouveau_ttm_vm_ops; -static const struct vm_operations_struct *ttm_vm_ops; - -static int -nouveau_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct ttm_buffer_object *bo = vma->vm_private_data; - int ret; - - if (unlikely(bo == NULL)) - return VM_FAULT_NOPAGE; - - ret = ttm_vm_ops->fault(vma, vmf); - return ret; -} - int nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; struct drm_nouveau_private *dev_priv = file_priv->minor->dev->dev_private; - int ret; if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) return drm_mmap(filp, vma); - ret = ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev); - if (unlikely(ret != 0)) - return ret; - - if (unlikely(ttm_vm_ops == NULL)) { - ttm_vm_ops = vma->vm_ops; - nouveau_ttm_vm_ops = *ttm_vm_ops; - nouveau_ttm_vm_ops.fault = &nouveau_ttm_fault; - } - - vma->vm_ops = &nouveau_ttm_vm_ops; - return 0; + return ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev); } static int -- cgit v1.2.3-70-g09d2 From 7978b9cfa59133a34aaad420e447c2a29d5c6152 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 6 Jan 2010 12:00:02 +1000 Subject: drm/nv50: prevent a possible ctxprog hang The below is mainly an educated guess at what's going on, docs would sure be handy... NVIDIA? :P It appears it's possible for a ctxprog to run even while a GPU exception is pending. The GF8 and up ctxprogs appear to have a small snippet of code which detects this, and stalls the ctxprog until it's been handled, which essentially looks like: if (r2 & 0x00008000) { r0 |= 0x80000000; while (r0 & 0x80000000) {} } I don't know of any way that flag would get cleared unless the driver intervenes (and indeed, in the cases I've seen the hang, nothing steps in to automagically clear it for us). This patch causes the driver to clear the flag during the PGRAPH IRQ handler. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_irq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 370c72c968d..919a619ca7f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -635,6 +635,7 @@ nv50_pgraph_irq_handler(struct drm_device *dev) if ((nv_rd32(dev, 0x400500) & isb) != isb) nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | isb); + nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); } nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); -- cgit v1.2.3-70-g09d2 From 234896a7671c23233230622728f6942b3d1c098e Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Wed, 6 Jan 2010 04:02:45 +0100 Subject: drm/nouveau: Fix null deref in nouveau_fence_emit due to deleted fence Currently Nouveau will unvalidate all buffers if it is forced to wait on one, and then start revalidating from the beginning. While doing so, it destroys the operation fence, causing nouveau_fence_emit to crash. This patch fixes this bug by taking the fence object out of validate_op and creating it just before emit. The fence pointer is initialized to 0 and unref'ed unconditionally. In addition to fixing the bug, this prevents its reintroduction and simplifies the code. Signed-off-by: Luca Barbieri Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_gem.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 18fd8ac9fca..2009db2426c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -220,7 +220,6 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, } struct validate_op { - struct nouveau_fence *fence; struct list_head vram_list; struct list_head gart_list; struct list_head both_list; @@ -252,17 +251,11 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence) } static void -validate_fini(struct validate_op *op, bool success) +validate_fini(struct validate_op *op, struct nouveau_fence* fence) { - struct nouveau_fence *fence = op->fence; - - if (unlikely(!success)) - op->fence = NULL; - - validate_fini_list(&op->vram_list, op->fence); - validate_fini_list(&op->gart_list, op->fence); - validate_fini_list(&op->both_list, op->fence); - nouveau_fence_unref((void *)&fence); + validate_fini_list(&op->vram_list, fence); + validate_fini_list(&op->gart_list, fence); + validate_fini_list(&op->both_list, fence); } static int @@ -420,10 +413,6 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, INIT_LIST_HEAD(&op->gart_list); INIT_LIST_HEAD(&op->both_list); - ret = nouveau_fence_new(chan, &op->fence, false); - if (ret) - return ret; - if (nr_buffers == 0) return 0; @@ -541,6 +530,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, struct drm_nouveau_gem_pushbuf_bo *bo = NULL; struct nouveau_channel *chan; struct validate_op op; + struct nouveau_fence* fence = 0; uint32_t *pushbuf = NULL; int ret = 0, do_reloc = 0, i; @@ -597,7 +587,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, OUT_RINGp(chan, pushbuf, req->nr_dwords); - ret = nouveau_fence_emit(op.fence); + ret = nouveau_fence_new(chan, &fence, true); if (ret) { NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); WIND_RING(chan); @@ -605,7 +595,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, } if (nouveau_gem_pushbuf_sync(chan)) { - ret = nouveau_fence_wait(op.fence, NULL, false, false); + ret = nouveau_fence_wait(fence, NULL, false, false); if (ret) { for (i = 0; i < req->nr_dwords; i++) NV_ERROR(dev, "0x%08x\n", pushbuf[i]); @@ -614,7 +604,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, } out: - validate_fini(&op, ret == 0); + validate_fini(&op, fence); + nouveau_fence_unref((void**)&fence); mutex_unlock(&dev->struct_mutex); kfree(pushbuf); kfree(bo); @@ -634,6 +625,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, struct drm_gem_object *gem; struct nouveau_bo *pbbo; struct validate_op op; + struct nouveau_fence* fence = 0; int i, ret = 0, do_reloc = 0; NOUVEAU_CHECK_INITIALISED_WITH_RETURN; @@ -772,7 +764,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, OUT_RING(chan, 0); } - ret = nouveau_fence_emit(op.fence); + ret = nouveau_fence_new(chan, &fence, true); if (ret) { NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); WIND_RING(chan); @@ -780,7 +772,8 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, } out: - validate_fini(&op, ret == 0); + validate_fini(&op, fence); + nouveau_fence_unref((void**)&fence); mutex_unlock(&dev->struct_mutex); kfree(bo); -- cgit v1.2.3-70-g09d2 From 1dee7a930bfddd69825fca3e3f9541c8a5333876 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 7 Jan 2010 13:47:57 +1000 Subject: drm/nv04: differentiate between nv04/nv05 Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_state.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index a6b573e8982..09b9a46dfc0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -642,7 +642,10 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) dev_priv->chipset = (reg0 & 0xff00000) >> 20; /* NV04 or NV05 */ } else if ((reg0 & 0xff00fff0) == 0x20004000) { - dev_priv->chipset = 0x04; + if (reg0 & 0x00f00000) + dev_priv->chipset = 0x05; + else + dev_priv->chipset = 0x04; } else dev_priv->chipset = 0xff; -- cgit v1.2.3-70-g09d2 From dff36321497b1130085820c81a44779b065c8d7e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 8 Jan 2010 10:53:40 +1000 Subject: drm/nouveau: use dma.max rather than pushbuf size for checking GET validity Some upcoming G80 DMA changes will depend on this, but it's split out for bisectibility just in case it causes some unexpected issues. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index f1fd3f2b981..3f7f78e03d4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -130,7 +130,7 @@ READ_GET(struct nouveau_channel *chan, uint32_t *get) val = nvchan_rd32(chan, chan->user_get); if (val < chan->pushbuf_base || - val >= chan->pushbuf_base + chan->pushbuf_bo->bo.mem.size) { + val > chan->pushbuf_base + (chan->dma.max << 2)) { /* meaningless to dma_wait() except to know whether the * GPU has stalled or not */ -- cgit v1.2.3-70-g09d2 From 75c99da6cdd0ec9d70747f9ced3e85b2dd955cdf Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 8 Jan 2010 10:57:39 +1000 Subject: drm/nouveau: initialise DMA tracking parameters earlier Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_channel.c | 2 ++ drivers/gpu/drm/nouveau/nouveau_dma.c | 15 +++++++++------ drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index d1c7f8c911c..343d718a966 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -158,6 +158,8 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, return ret; } + nouveau_dma_pre_init(chan); + /* Locate channel's user control regs */ if (dev_priv->card_type < NV_40) user = NV03_USER(channel); diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index 3f7f78e03d4..7afbe8b40d5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -29,6 +29,15 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" +void +nouveau_dma_pre_init(struct nouveau_channel *chan) +{ + chan->dma.max = (chan->pushbuf_bo->bo.mem.size >> 2) - 2; + chan->dma.put = 0; + chan->dma.cur = chan->dma.put; + chan->dma.free = chan->dma.max - chan->dma.cur; +} + int nouveau_dma_init(struct nouveau_channel *chan) { @@ -74,12 +83,6 @@ nouveau_dma_init(struct nouveau_channel *chan) return ret; } - /* Initialise DMA vars */ - chan->dma.max = (chan->pushbuf_bo->bo.mem.size >> 2) - 2; - chan->dma.put = 0; - chan->dma.cur = chan->dma.put; - chan->dma.free = chan->dma.max - chan->dma.cur; - /* Insert NOPS for NOUVEAU_DMA_SKIPS */ ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 4087a9a20ba..026419fe879 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -837,6 +837,7 @@ nouveau_debugfs_channel_fini(struct nouveau_channel *chan) #endif /* nouveau_dma.c */ +extern void nouveau_dma_pre_init(struct nouveau_channel *); extern int nouveau_dma_init(struct nouveau_channel *); extern int nouveau_dma_wait(struct nouveau_channel *, int size); -- cgit v1.2.3-70-g09d2 From fe5a64acbfab4f79ccd18972c3d4c1cae31f3b8d Mon Sep 17 00:00:00 2001 From: Marcin Kościelnicki Date: Sun, 10 Jan 2010 17:09:14 +0000 Subject: drm/nv04: Fix set_operation software method. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv04_graph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c index 98f3b40318d..e260986ea65 100644 --- a/drivers/gpu/drm/nouveau/nv04_graph.c +++ b/drivers/gpu/drm/nouveau/nv04_graph.c @@ -537,7 +537,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, int mthd, uint32_t data) { struct drm_device *dev = chan->dev; - uint32_t instance = nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff; + uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; uint32_t tmp; -- cgit v1.2.3-70-g09d2 From e6edbdc52bc0755cbfe0721ca91d4fd87649bc13 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sun, 10 Jan 2010 23:59:05 -0800 Subject: Input: i8042 - add Dritek quirk for Acer Aspire 5610. Signed-off-by: Elliott Sales de Andrade Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 64b688daf48..2a5982e532f 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -523,6 +523,13 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { * have turned up in 2007 that also need this again. */ static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { + { + /* Acer Aspire 5610 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), + }, + }, { /* Acer Aspire 5630 */ .matches = { -- cgit v1.2.3-70-g09d2 From b27d7f16d3c6c27345d4280a739809c1c2c4c0b5 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Mon, 11 Jan 2010 03:21:50 -0500 Subject: DM: Fix device mapper topology stacking Make DM use bdev_stack_limits() function so that partition offsets get taken into account when calculating alignment. Clarify stacking warnings. Also remove obsolete clearing of final alignment_offset and misalignment flag. Signed-off-by: Martin K. Petersen Signed-off-by: Mike Snitzer Cc: Alasdair G. Kergon Signed-off-by: Jens Axboe --- drivers/md/dm-table.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index be625475cf6..4b22feb01a0 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -503,16 +503,15 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev, return 0; } - if (blk_stack_limits(limits, &q->limits, start << 9) < 0) - DMWARN("%s: target device %s is misaligned: " + if (bdev_stack_limits(limits, bdev, start) < 0) + DMWARN("%s: adding target device %s caused an alignment inconsistency: " "physical_block_size=%u, logical_block_size=%u, " "alignment_offset=%u, start=%llu", dm_device_name(ti->table->md), bdevname(bdev, b), q->limits.physical_block_size, q->limits.logical_block_size, q->limits.alignment_offset, - (unsigned long long) start << 9); - + (unsigned long long) start << SECTOR_SHIFT); /* * Check if merge fn is supported. @@ -1026,9 +1025,9 @@ combine_limits: * for the table. */ if (blk_stack_limits(limits, &ti_limits, 0) < 0) - DMWARN("%s: target device " + DMWARN("%s: adding target device " "(start sect %llu len %llu) " - "is misaligned", + "caused an alignment inconsistency", dm_device_name(table->md), (unsigned long long) ti->begin, (unsigned long long) ti->len); @@ -1079,15 +1078,6 @@ no_integrity: void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, struct queue_limits *limits) { - /* - * Each target device in the table has a data area that should normally - * be aligned such that the DM device's alignment_offset is 0. - * FIXME: Propagate alignment_offsets up the stack and warn of - * sub-optimal or inconsistent settings. - */ - limits->alignment_offset = 0; - limits->misaligned = 0; - /* * Copy table's limits to the DM device's request_queue */ -- cgit v1.2.3-70-g09d2 From 23978161f90e5a3200ad6ac9b0d534911e4cbb28 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 11 Jan 2010 16:17:12 +0100 Subject: drivers/block/drbd/drbd_receiver.c: correct NULL test Test the just-allocated value for NULL rather than some other value. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,y; statement S; @@ x = \(kmalloc\|kcalloc\|kzalloc\)(...); ( if ((x) == NULL) S | if ( - y + x == NULL) S ) // Signed-off-by: Julia Lawall Cc: Lars Ellenberg Cc: Philipp Reisner Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/drbd/drbd_receiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index a6d266ee7e2..dbd451984e0 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3945,7 +3945,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) } right_response = kmalloc(resp_size, GFP_NOIO); - if (response == NULL) { + if (right_response == NULL) { dev_err(DEV, "kmalloc of right_response failed\n"); rv = 0; goto fail; -- cgit v1.2.3-70-g09d2 From 39825f4dc9f4e409e8ea43ef4df04a924699ad1f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 9 Jan 2010 11:41:48 +0300 Subject: iwlwifi: silence buffer overflow warning Smatch (and presumably other static checkers) complain that MAX_TID_COUNT is past the end of the array. In the resulting discussion, Zhu Yi pointed out that this value is not used in real life and the assignment was only there to silence a gcc warning. If there were a bug in the surrounding code and the value were used, the WARN_ON(!qc) would print a warning before the crash. Signed-off-by: Dan Carpenter Acked-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 761aab127e7..9b4b8b5c757 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1961,7 +1961,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, struct ieee80211_tx_info *info; struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->u.status); - int tid = MAX_TID_COUNT - 1; + int uninitialized_var(tid); int sta_id; int freed; u8 *qc = NULL; -- cgit v1.2.3-70-g09d2 From b10d96cb9c9a2a0029d28910ca517f4003051b04 Mon Sep 17 00:00:00 2001 From: Johannes Thoma Date: Thu, 7 Jan 2010 16:02:50 +0100 Subject: drbd: Don't go into StandAlone mode when authentification failes because of network error Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index dbd451984e0..e3716fadc6a 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -878,9 +878,13 @@ retry: if (mdev->cram_hmac_tfm) { /* drbd_request_state(mdev, NS(conn, WFAuth)); */ - if (!drbd_do_auth(mdev)) { + switch (drbd_do_auth(mdev)) { + case -1: dev_err(DEV, "Authentication of peer failed\n"); return -1; + case 0: + dev_err(DEV, "Authentication of peer failed, trying again.\n"); + return 0; } } @@ -3831,10 +3835,17 @@ static int drbd_do_auth(struct drbd_conf *mdev) { dev_err(DEV, "This kernel was build without CONFIG_CRYPTO_HMAC.\n"); dev_err(DEV, "You need to disable 'cram-hmac-alg' in drbd.conf.\n"); - return 0; + return -1; } #else #define CHALLENGE_LEN 64 + +/* Return value: + 1 - auth succeeded, + 0 - failed, try again (network error), + -1 - auth failed, don't try again. +*/ + static int drbd_do_auth(struct drbd_conf *mdev) { char my_challenge[CHALLENGE_LEN]; /* 64 Bytes... */ @@ -3855,7 +3866,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) (u8 *)mdev->net_conf->shared_secret, key_len); if (rv) { dev_err(DEV, "crypto_hash_setkey() failed with %d\n", rv); - rv = 0; + rv = -1; goto fail; } @@ -3878,14 +3889,14 @@ static int drbd_do_auth(struct drbd_conf *mdev) if (p.length > CHALLENGE_LEN*2) { dev_err(DEV, "expected AuthChallenge payload too big.\n"); - rv = 0; + rv = -1; goto fail; } peers_ch = kmalloc(p.length, GFP_NOIO); if (peers_ch == NULL) { dev_err(DEV, "kmalloc of peers_ch failed\n"); - rv = 0; + rv = -1; goto fail; } @@ -3901,7 +3912,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) response = kmalloc(resp_size, GFP_NOIO); if (response == NULL) { dev_err(DEV, "kmalloc of response failed\n"); - rv = 0; + rv = -1; goto fail; } @@ -3911,7 +3922,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) rv = crypto_hash_digest(&desc, &sg, sg.length, response); if (rv) { dev_err(DEV, "crypto_hash_digest() failed with %d\n", rv); - rv = 0; + rv = -1; goto fail; } @@ -3947,7 +3958,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) right_response = kmalloc(resp_size, GFP_NOIO); if (right_response == NULL) { dev_err(DEV, "kmalloc of right_response failed\n"); - rv = 0; + rv = -1; goto fail; } @@ -3956,7 +3967,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) rv = crypto_hash_digest(&desc, &sg, sg.length, right_response); if (rv) { dev_err(DEV, "crypto_hash_digest() failed with %d\n", rv); - rv = 0; + rv = -1; goto fail; } @@ -3965,6 +3976,8 @@ static int drbd_do_auth(struct drbd_conf *mdev) if (rv) dev_info(DEV, "Peer authenticated using %d bytes of '%s' HMAC\n", resp_size, mdev->net_conf->cram_hmac_alg); + else + rv = -1; fail: kfree(peers_ch); -- cgit v1.2.3-70-g09d2 From a393db6f10ef2d4f28257234cfc730e744dfb6a4 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 22 Dec 2009 13:35:52 +0100 Subject: drbd: Allow online resizing of DRBD devices while peer not reachable (needs to be explicitly forced) Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 5 ++--- drivers/block/drbd/drbd_nl.c | 17 +++++++++++------ drivers/block/drbd/drbd_receiver.c | 4 ++-- include/linux/drbd_nl.h | 1 + 4 files changed, 16 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 79d8e22c4d0..2bf3a6ef368 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1371,10 +1371,9 @@ extern int is_valid_ar_handle(struct drbd_request *, sector_t); extern void drbd_suspend_io(struct drbd_conf *mdev); extern void drbd_resume_io(struct drbd_conf *mdev); extern char *ppsize(char *buf, unsigned long long size); -extern sector_t drbd_new_dev_size(struct drbd_conf *, - struct drbd_backing_dev *); +extern sector_t drbd_new_dev_size(struct drbd_conf *, struct drbd_backing_dev *, int); enum determine_dev_size { dev_size_error = -1, unchanged = 0, shrunk = 1, grew = 2 }; -extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *) __must_hold(local); +extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *, int force) __must_hold(local); extern void resync_after_online_grow(struct drbd_conf *); extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local); extern int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 3313901a486..1292e062066 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -510,7 +510,7 @@ void drbd_resume_io(struct drbd_conf *mdev) * Returns 0 on success, negative return values indicate errors. * You should call drbd_md_sync() after calling this function. */ -enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev) __must_hold(local) +enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, int force) __must_hold(local) { sector_t prev_first_sect, prev_size; /* previous meta location */ sector_t la_size; @@ -541,7 +541,7 @@ enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev) __must_ho /* TODO: should only be some assert here, not (re)init... */ drbd_md_set_sector_offsets(mdev, mdev->ldev); - size = drbd_new_dev_size(mdev, mdev->ldev); + size = drbd_new_dev_size(mdev, mdev->ldev, force); if (drbd_get_capacity(mdev->this_bdev) != size || drbd_bm_capacity(mdev) != size) { @@ -596,7 +596,7 @@ out: } sector_t -drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) +drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, int assume_peer_has_space) { sector_t p_size = mdev->p_size; /* partner's disk size. */ sector_t la_size = bdev->md.la_size_sect; /* last agreed size. */ @@ -606,6 +606,11 @@ drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) m_size = drbd_get_max_capacity(bdev); + if (mdev->state.conn < C_CONNECTED && assume_peer_has_space) { + dev_warn(DEV, "Resize while not connected was forced by the user!\n"); + p_size = m_size; + } + if (p_size && m_size) { size = min_t(sector_t, p_size, m_size); } else { @@ -965,7 +970,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp /* Prevent shrinking of consistent devices ! */ if (drbd_md_test_flag(nbc, MDF_CONSISTENT) && - drbd_new_dev_size(mdev, nbc) < nbc->md.la_size_sect) { + drbd_new_dev_size(mdev, nbc, 0) < nbc->md.la_size_sect) { dev_warn(DEV, "refusing to truncate a consistent device\n"); retcode = ERR_DISK_TO_SMALL; goto force_diskless_dec; @@ -1052,7 +1057,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp !drbd_md_test_flag(mdev->ldev, MDF_CONNECTED_IND)) set_bit(USE_DEGR_WFC_T, &mdev->flags); - dd = drbd_determin_dev_size(mdev); + dd = drbd_determin_dev_size(mdev, 0); if (dd == dev_size_error) { retcode = ERR_NOMEM_BITMAP; goto force_diskless_dec; @@ -1504,7 +1509,7 @@ static int drbd_nl_resize(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, } mdev->ldev->dc.disk_size = (sector_t)rs.resize_size; - dd = drbd_determin_dev_size(mdev); + dd = drbd_determin_dev_size(mdev, rs.resize_force); drbd_md_sync(mdev); put_ldev(mdev); if (dd == dev_size_error) { diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index e3716fadc6a..f22a5283128 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2870,7 +2870,7 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header *h) /* Never shrink a device with usable data during connect. But allow online shrinking if we are connected. */ - if (drbd_new_dev_size(mdev, mdev->ldev) < + if (drbd_new_dev_size(mdev, mdev->ldev, 0) < drbd_get_capacity(mdev->this_bdev) && mdev->state.disk >= D_OUTDATED && mdev->state.conn < C_CONNECTED) { @@ -2885,7 +2885,7 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header *h) #undef min_not_zero if (get_ldev(mdev)) { - dd = drbd_determin_dev_size(mdev); + dd = drbd_determin_dev_size(mdev, 0); put_ldev(mdev); if (dd == dev_size_error) return FALSE; diff --git a/include/linux/drbd_nl.h b/include/linux/drbd_nl.h index db5721ad50d..a4d82f89599 100644 --- a/include/linux/drbd_nl.h +++ b/include/linux/drbd_nl.h @@ -69,6 +69,7 @@ NL_PACKET(disconnect, 6, ) NL_PACKET(resize, 7, NL_INT64( 29, T_MAY_IGNORE, resize_size) + NL_BIT( 68, T_MAY_IGNORE, resize_force) ) NL_PACKET(syncer_conf, 8, -- cgit v1.2.3-70-g09d2 From ff998793288b49a3b22d929bf8e56362320905ff Mon Sep 17 00:00:00 2001 From: Peter Horton Date: Tue, 5 Jan 2010 11:14:36 +0000 Subject: UBI: initialise update marker The in kernel copy of a volume's update marker is not initialised from the volume table. This means that volumes where an update was unfinnished will not be treated as "forbidden to use". This is basically that the update functionality was broken. Signed-off-by: Peter Horton Signed-off-by: Artem Bityutskiy Cc: stable@kernel.org --- drivers/mtd/ubi/vtbl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 1afc61e7455..40044028d68 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -566,6 +566,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, vol->reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs); vol->alignment = be32_to_cpu(vtbl[i].alignment); vol->data_pad = be32_to_cpu(vtbl[i].data_pad); + vol->upd_marker = vtbl[i].upd_marker; vol->vol_type = vtbl[i].vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME; vol->name_len = be16_to_cpu(vtbl[i].name_len); -- cgit v1.2.3-70-g09d2 From b531b55a7bde8aa2bdf7023b3afc6df1bf3dcb67 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 5 Jan 2010 17:25:59 +0200 Subject: UBI: add more checks to chdev open When opening UBI volumes by their character device names, make sure we are opening character devices, not block devices or any other inode type. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/kapi.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 277786ebaa2..1361574e2b0 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -291,8 +291,7 @@ EXPORT_SYMBOL_GPL(ubi_open_volume_nm); */ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) { - int error, ubi_num, vol_id; - struct ubi_volume_desc *ret; + int error, ubi_num, vol_id, mod; struct inode *inode; struct path path; @@ -306,16 +305,16 @@ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) return ERR_PTR(error); inode = path.dentry->d_inode; + mod = inode->i_mode; ubi_num = ubi_major2num(imajor(inode)); vol_id = iminor(inode) - 1; + path_put(&path); + if (!S_ISCHR(mod)) + return ERR_PTR(-EINVAL); if (vol_id >= 0 && ubi_num >= 0) - ret = ubi_open_volume(ubi_num, vol_id, mode); - else - ret = ERR_PTR(-ENODEV); - - path_put(&path); - return ret; + return ubi_open_volume(ubi_num, vol_id, mode); + return ERR_PTR(-ENODEV); } EXPORT_SYMBOL_GPL(ubi_open_volume_path); -- cgit v1.2.3-70-g09d2 From 15e184afa83a45cf8bafdb9dc906b97a8fbc974f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 11 Jan 2010 00:05:43 -0800 Subject: Input: add compat support for sysfs and /proc capabilities output Input core displays capabilities bitmasks in form of one or more longs printed in hex form and separated by spaces. Unfortunately it does not work well for 32-bit applications running on 64-bit kernels since applications expect that number is "worth" only 32 bits when kernel advances by 64 bits. Fix that by ensuring that output produced for compat tasks uses 32-bit units. Reported-and-tested-by: Michael Tokarev Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 86 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/input/input.c b/drivers/input/input.c index ab060710688..30b503b8d67 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -24,6 +24,7 @@ #include #include #include +#include "input-compat.h" MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Input core"); @@ -764,6 +765,40 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han return error; } +#ifdef CONFIG_COMPAT + +static int input_bits_to_string(char *buf, int buf_size, + unsigned long bits, bool skip_empty) +{ + int len = 0; + + if (INPUT_COMPAT_TEST) { + u32 dword = bits >> 32; + if (dword || !skip_empty) + len += snprintf(buf, buf_size, "%x ", dword); + + dword = bits & 0xffffffffUL; + if (dword || !skip_empty || len) + len += snprintf(buf + len, max(buf_size - len, 0), + "%x", dword); + } else { + if (bits || !skip_empty) + len += snprintf(buf, buf_size, "%lx", bits); + } + + return len; +} + +#else /* !CONFIG_COMPAT */ + +static int input_bits_to_string(char *buf, int buf_size, + unsigned long bits, bool skip_empty) +{ + return bits || !skip_empty ? + snprintf(buf, buf_size, "%lx", bits) : 0; +} + +#endif #ifdef CONFIG_PROC_FS @@ -832,14 +867,25 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name, unsigned long *bitmap, int max) { int i; - - for (i = BITS_TO_LONGS(max) - 1; i > 0; i--) - if (bitmap[i]) - break; + bool skip_empty = true; + char buf[18]; seq_printf(seq, "B: %s=", name); - for (; i >= 0; i--) - seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : ""); + + for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) { + if (input_bits_to_string(buf, sizeof(buf), + bitmap[i], skip_empty)) { + skip_empty = false; + seq_printf(seq, "%s%s", buf, i > 0 ? " " : ""); + } + } + + /* + * If no output was produced print a single 0. + */ + if (skip_empty) + seq_puts(seq, "0"); + seq_putc(seq, '\n'); } @@ -1128,14 +1174,23 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, { int i; int len = 0; + bool skip_empty = true; + + for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) { + len += input_bits_to_string(buf + len, max(buf_size - len, 0), + bitmap[i], skip_empty); + if (len) { + skip_empty = false; + if (i > 0) + len += snprintf(buf + len, max(buf_size - len, 0), " "); + } + } - for (i = BITS_TO_LONGS(max) - 1; i > 0; i--) - if (bitmap[i]) - break; - - for (; i >= 0; i--) - len += snprintf(buf + len, max(buf_size - len, 0), - "%lx%s", bitmap[i], i > 0 ? " " : ""); + /* + * If no output was produced print a single 0. + */ + if (len == 0) + len = snprintf(buf, buf_size, "%d", 0); if (add_cr) len += snprintf(buf + len, max(buf_size - len, 0), "\n"); @@ -1150,7 +1205,8 @@ static ssize_t input_dev_show_cap_##bm(struct device *dev, \ { \ struct input_dev *input_dev = to_input_dev(dev); \ int len = input_print_bitmap(buf, PAGE_SIZE, \ - input_dev->bm##bit, ev##_MAX, 1); \ + input_dev->bm##bit, ev##_MAX, \ + true); \ return min_t(int, len, PAGE_SIZE); \ } \ static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL) @@ -1214,7 +1270,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env, len = input_print_bitmap(&env->buf[env->buflen - 1], sizeof(env->buf) - env->buflen, - bitmap, max, 0); + bitmap, max, false); if (len >= (sizeof(env->buf) - env->buflen)) return -ENOMEM; -- cgit v1.2.3-70-g09d2 From d8e292093a3a78a7967757e90abbe64869e4cb7c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 9 Jan 2010 00:45:33 +0100 Subject: drm/i915: Fix resume regression on MSI Wind U100 w/o KMS Commit cbda12d77ea590082edb6d30bd342a67ebc459e0 (drm/i915: implement new pm ops for i915), among other things, removed the .suspend and .resume pointers from the struct drm_driver object in i915_drv.c, which broke resume without KMS on my MSI Wind U100. Fix this by reverting that part of commit cbda12d77ea59. Signed-off-by: Rafael J. Wysocki Acked-by: Jesse Barnes [anholt: added comment explaining when .suspend/.resume matter] Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2ffffd7ae09..66f7bac2ee5 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -464,6 +464,11 @@ static struct drm_driver driver = { .lastclose = i915_driver_lastclose, .preclose = i915_driver_preclose, .postclose = i915_driver_postclose, + + /* Used in place of i915_pm_ops for non-DRIVER_MODESET */ + .suspend = i915_suspend, + .resume = i915_resume, + .device_is_agp = i915_driver_device_is_agp, .enable_vblank = i915_enable_vblank, .disable_vblank = i915_disable_vblank, -- cgit v1.2.3-70-g09d2 From 6207937d4feea000913e8ca23fe20c7744be7847 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 09:49:31 +0800 Subject: drm/i915: Don't use the child device parsed from VBT to setup HDMI/DP On some boxes the BIOS will report different child device arrays when the system is booted with/without the dock. In such case the HDMI/DP port can't be setup correctly. So revert two commits (fc816655236cd9da162356e96e74c7cfb0834d92/ 6e36595a2131e7ed5ee2674be54b2713ba7f0490) that use the child device parsed from VBT to setup HDMI/DP. http://bugzilla.kernel.org/show_bug.cgi?id=14854 http://bugzilla.kernel.org/show_bug.cgi?id=14860 Signed-off-by: Zhao Yakui Tested-by: Sean Young Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_dp.c | 52 +-------------------------------------- drivers/gpu/drm/i915/intel_hdmi.c | 50 ------------------------------------- 2 files changed, 1 insertion(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1349d9fd01c..0ec07e43d6c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1289,53 +1289,7 @@ intel_dp_hot_plug(struct intel_output *intel_output) if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON) intel_dp_check_link_status(intel_output); } -/* - * Enumerate the child dev array parsed from VBT to check whether - * the given DP is present. - * If it is present, return 1. - * If it is not present, return false. - * If no child dev is parsed from VBT, it is assumed that the given - * DP is present. - */ -static int dp_is_present_in_vbt(struct drm_device *dev, int dp_reg) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct child_device_config *p_child; - int i, dp_port, ret; - - if (!dev_priv->child_dev_num) - return 1; - - dp_port = 0; - if (dp_reg == DP_B || dp_reg == PCH_DP_B) - dp_port = PORT_IDPB; - else if (dp_reg == DP_C || dp_reg == PCH_DP_C) - dp_port = PORT_IDPC; - else if (dp_reg == DP_D || dp_reg == PCH_DP_D) - dp_port = PORT_IDPD; - - ret = 0; - for (i = 0; i < dev_priv->child_dev_num; i++) { - p_child = dev_priv->child_dev + i; - /* - * If the device type is not DP, continue. - */ - if (p_child->device_type != DEVICE_TYPE_DP && - p_child->device_type != DEVICE_TYPE_eDP) - continue; - /* Find the eDP port */ - if (dp_reg == DP_A && p_child->device_type == DEVICE_TYPE_eDP) { - ret = 1; - break; - } - /* Find the DP port */ - if (p_child->dvo_port == dp_port) { - ret = 1; - break; - } - } - return ret; -} + void intel_dp_init(struct drm_device *dev, int output_reg) { @@ -1345,10 +1299,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) struct intel_dp_priv *dp_priv; const char *name = NULL; - if (!dp_is_present_in_vbt(dev, output_reg)) { - DRM_DEBUG_KMS("DP is not present. Ignore it\n"); - return; - } intel_output = kcalloc(sizeof(struct intel_output) + sizeof(struct intel_dp_priv), 1, GFP_KERNEL); if (!intel_output) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 06431941b23..0e268deed76 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -225,52 +225,6 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { .destroy = intel_hdmi_enc_destroy, }; -/* - * Enumerate the child dev array parsed from VBT to check whether - * the given HDMI is present. - * If it is present, return 1. - * If it is not present, return false. - * If no child dev is parsed from VBT, it assumes that the given - * HDMI is present. - */ -static int hdmi_is_present_in_vbt(struct drm_device *dev, int hdmi_reg) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct child_device_config *p_child; - int i, hdmi_port, ret; - - if (!dev_priv->child_dev_num) - return 1; - - if (hdmi_reg == SDVOB) - hdmi_port = DVO_B; - else if (hdmi_reg == SDVOC) - hdmi_port = DVO_C; - else if (hdmi_reg == HDMIB) - hdmi_port = DVO_B; - else if (hdmi_reg == HDMIC) - hdmi_port = DVO_C; - else if (hdmi_reg == HDMID) - hdmi_port = DVO_D; - else - return 0; - - ret = 0; - for (i = 0; i < dev_priv->child_dev_num; i++) { - p_child = dev_priv->child_dev + i; - /* - * If the device type is not HDMI, continue. - */ - if (p_child->device_type != DEVICE_TYPE_HDMI) - continue; - /* Find the HDMI port */ - if (p_child->dvo_port == hdmi_port) { - ret = 1; - break; - } - } - return ret; -} void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -278,10 +232,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) struct intel_output *intel_output; struct intel_hdmi_priv *hdmi_priv; - if (!hdmi_is_present_in_vbt(dev, sdvox_reg)) { - DRM_DEBUG_KMS("HDMI is not present. Ignored it \n"); - return; - } intel_output = kcalloc(sizeof(struct intel_output) + sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); if (!intel_output) -- cgit v1.2.3-70-g09d2 From 6a304caf0bf9c429fc261f260b86cabf5bde2cbb Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 10:58:19 +0800 Subject: drm/i915: Read the response after issuing DDC bus switch command For some SDVO cards based on conexant chip, we can't read the EDID if we don't read the response after issuing SDVO DDC bus switch command. From the SDVO spec once when another I2C transaction is finished after completing the I2C transaction of issuing the bus switch command, it will be switched back to the SDVO internal state again. So we can't initiate a new I2C transaction to read the response after issuing the DDC bus switch command. Instead we should issue DDC bus switch command and read the response in the same I2C transaction. https://bugs.freedesktop.org/show_bug.cgi?id=23842 https://bugs.freedesktop.org/show_bug.cgi?id=24458 https://bugs.freedesktop.org/show_bug.cgi?id=24522 https://bugs.freedesktop.org/show_bug.cgi?id=24282 Signed-off-by: Zhao Yakui Tested-by: Sebastien Caty Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_sdvo.c | 57 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index de5144c8c15..f899afd924b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -462,14 +462,63 @@ static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) } /** - * Don't check status code from this as it switches the bus back to the - * SDVO chips which defeats the purpose of doing a bus switch in the first - * place. + * Try to read the response after issuie the DDC switch command. But it + * is noted that we must do the action of reading response and issuing DDC + * switch command in one I2C transaction. Otherwise when we try to start + * another I2C transaction after issuing the DDC bus switch, it will be + * switched to the internal SDVO register. */ static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output, u8 target) { - intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1); + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u8 out_buf[2], cmd_buf[2], ret_value[2], ret; + struct i2c_msg msgs[] = { + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = 0, + .len = 2, + .buf = out_buf, + }, + /* the following two are to read the response */ + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = 0, + .len = 1, + .buf = cmd_buf, + }, + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = I2C_M_RD, + .len = 1, + .buf = ret_value, + }, + }; + + intel_sdvo_debug_write(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, + &target, 1); + /* write the DDC switch command argument */ + intel_sdvo_write_byte(intel_output, SDVO_I2C_ARG_0, target); + + out_buf[0] = SDVO_I2C_OPCODE; + out_buf[1] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; + cmd_buf[0] = SDVO_I2C_CMD_STATUS; + cmd_buf[1] = 0; + ret_value[0] = 0; + ret_value[1] = 0; + + ret = i2c_transfer(intel_output->i2c_bus, msgs, 3); + if (ret != 3) { + /* failure in I2C transfer */ + DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); + return; + } + if (ret_value[0] != SDVO_CMD_STATUS_SUCCESS) { + DRM_DEBUG_KMS("DDC switch command returns response %d\n", + ret_value[0]); + return; + } + return; } static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool target_0, bool target_1) -- cgit v1.2.3-70-g09d2 From 7c3f0a2726fed78e0e0afe3b6fc3c1f5b298e447 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 10:58:20 +0800 Subject: drm/i915: try another possible DDC bus for the SDVO device with multiple outputs There exist multiple DDC buses for the SDVO cards with multiple outputs. When we can't get the EDID by using the select DDC bus, we can try the other possible DDC bus to see whether the EDID can be obtained. https://bugs.freedesktop.org/show_bug.cgi?id=23842 Signed-off-by: Zhao Yakui Tested-by: Sebastien Caty Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_sdvo.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f899afd924b..eaacfd0920d 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1628,6 +1628,32 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response) edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus); + /* This is only applied to SDVO cards with multiple outputs */ + if (edid == NULL && intel_sdvo_multifunc_encoder(intel_output)) { + uint8_t saved_ddc, temp_ddc; + saved_ddc = sdvo_priv->ddc_bus; + temp_ddc = sdvo_priv->ddc_bus >> 1; + /* + * Don't use the 1 as the argument of DDC bus switch to get + * the EDID. It is used for SDVO SPD ROM. + */ + while(temp_ddc > 1) { + sdvo_priv->ddc_bus = temp_ddc; + edid = drm_get_edid(&intel_output->base, + intel_output->ddc_bus); + if (edid) { + /* + * When we can get the EDID, maybe it is the + * correct DDC bus. Update it. + */ + sdvo_priv->ddc_bus = temp_ddc; + break; + } + temp_ddc >>= 1; + } + if (edid == NULL) + sdvo_priv->ddc_bus = saved_ddc; + } /* when there is no edid and no monitor is connected with VGA * port, try to use the CRT ddc to read the EDID for DVI-connector */ -- cgit v1.2.3-70-g09d2 From b9241ea31fae4887104e5d1b3b18f4009c25a0c4 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 25 Nov 2009 13:09:39 +0800 Subject: drm/i915: Don't wait interruptible for possible plane buffer flush When we setup buffer for display plane, we'll check any pending required GPU flush and possible make interruptible wait for flush complete. But that wait would be most possibly to fail in case of signals received for X process, which will then fail modeset process and put display engine in unconsistent state. The result could be blank screen or CPU hang, and DDX driver would always turn on outputs DPMS after whatever modeset fails or not. So this one creates new helper for setup display plane buffer, and when needing flush using uninterruptible wait for that. This one should fix bug like https://bugs.freedesktop.org/show_bug.cgi?id=24009. Also fixing mode switch stress test on Ironlake. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 51 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 29dd6762696..445c49c6c39 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -864,6 +864,7 @@ int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptib int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write); +int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj); int i915_gem_attach_phys_object(struct drm_device *dev, struct drm_gem_object *obj, int id); void i915_gem_detach_phys_object(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2748609f05b..0f4afa3b03f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2837,6 +2837,57 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) return 0; } +/* + * Prepare buffer for display plane. Use uninterruptible for possible flush + * wait, as in modesetting process we're not supposed to be interrupted. + */ +int +i915_gem_object_set_to_display_plane(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + uint32_t old_write_domain, old_read_domains; + int ret; + + /* Not valid to be called on unbound objects. */ + if (obj_priv->gtt_space == NULL) + return -EINVAL; + + i915_gem_object_flush_gpu_write_domain(obj); + + /* Wait on any GPU rendering and flushing to occur. */ + if (obj_priv->active) { +#if WATCH_BUF + DRM_INFO("%s: object %p wait for seqno %08x\n", + __func__, obj, obj_priv->last_rendering_seqno); +#endif + ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0); + if (ret != 0) + return ret; + } + + old_write_domain = obj->write_domain; + old_read_domains = obj->read_domains; + + obj->read_domains &= I915_GEM_DOMAIN_GTT; + + i915_gem_object_flush_cpu_write_domain(obj); + + /* It should now be out of any other write domains, and we can update + * the domain values for our changes. + */ + BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); + obj->read_domains |= I915_GEM_DOMAIN_GTT; + obj->write_domain = I915_GEM_DOMAIN_GTT; + obj_priv->dirty = 1; + + trace_i915_gem_object_change_domain(obj, + old_read_domains, + old_write_domain); + + return 0; +} + /** * Moves a single object to the CPU read, and possibly write domain. * diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 42e8c031c2c..4b96a54b8e4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1207,7 +1207,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; } - ret = i915_gem_object_set_to_gtt_domain(obj, 1); + ret = i915_gem_object_set_to_display_plane(obj); if (ret != 0) { i915_gem_object_unpin(obj); mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3-70-g09d2 From 3890ddf56dbc0f804953198e65a7e406ed654576 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 12 Jan 2010 11:16:57 -0500 Subject: drm/radeon/kms: fix up LVDS handling on macs (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on radeonfb code and recent ddx fix. v2: minor formatting fix from Michel Dänzer Signed-off-by: Alex Deucher Reviewed-by: Michel Dänzer Tested-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 981508ff703..38e45e231ef 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -46,6 +46,7 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man; int panel_pwr_delay = 2000; + bool is_mac = false; DRM_DEBUG("\n"); if (radeon_encoder->enc_priv) { @@ -58,6 +59,15 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) } } + /* macs (and possibly some x86 oem systems?) wire up LVDS strangely + * Taken from radeonfb. + */ + if ((rdev->mode_info.connector_table == CT_IBOOK) || + (rdev->mode_info.connector_table == CT_POWERBOOK_EXTERNAL) || + (rdev->mode_info.connector_table == CT_POWERBOOK_INTERNAL) || + (rdev->mode_info.connector_table == CT_POWERBOOK_VGA)) + is_mac = true; + switch (mode) { case DRM_MODE_DPMS_ON: disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN); @@ -74,6 +84,8 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON); + if (is_mac) + lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN; lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); udelay(panel_pwr_delay * 1000); WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); @@ -85,7 +97,14 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; - lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); + if (is_mac) { + lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN; + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN); + } else { + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); + } udelay(panel_pwr_delay * 1000); WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); -- cgit v1.2.3-70-g09d2 From b042589ca038e647fa1e2bb4e7ac3963688479b8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Jan 2010 19:47:38 -0500 Subject: drm/radeon/kms/r6xx+: make irq handler less verbose Unhandled vectors can be safely ignored, no need to spam the kernel log by default. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 1f4f83d6fbe..9757962146f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2729,7 +2729,7 @@ restart_ih: } break; default: - DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); break; } break; @@ -2749,7 +2749,7 @@ restart_ih: } break; default: - DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); break; } break; @@ -2798,7 +2798,7 @@ restart_ih: } break; default: - DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); break; } break; @@ -2812,7 +2812,7 @@ restart_ih: DRM_DEBUG("IH: CP EOP\n"); break; default: - DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); break; } -- cgit v1.2.3-70-g09d2 From 1b24203e51072b6e76aff8c74bdd67eb3b34a724 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Jan 2010 15:02:31 -0500 Subject: drm/radeon/kms/rv100: reject modes > 135 Mhz on DVI (v2) Due to heat issues. Fixes fdo bug 25992 v2: fix typo noticed by Maarten Maathuis Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 9da10dd5df8..55266416fa4 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -900,10 +900,18 @@ static void radeon_dvi_force(struct drm_connector *connector) static int radeon_dvi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; struct radeon_connector *radeon_connector = to_radeon_connector(connector); /* XXX check mode bandwidth */ + /* clocks over 135 MHz have heat issues with DVI on RV100 */ + if (radeon_connector->use_digital && + (rdev->family == CHIP_RV100) && + (mode->clock > 135000)) + return MODE_CLOCK_HIGH; + if (radeon_connector->use_digital && (mode->clock > 165000)) { if ((radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) || (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) || -- cgit v1.2.3-70-g09d2 From 11f3b59e3654c66c4e8ef2c48f8138b78bf440da Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Mon, 11 Jan 2010 08:58:38 +0100 Subject: drm/radeon/kms: Fix crash getting TV info with no BIOS. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 7914455c96c..579c8920e08 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -687,6 +687,9 @@ radeon_combios_get_tv_info(struct radeon_device *rdev) uint16_t tv_info; enum radeon_tv_std tv_std = TV_STD_NTSC; + if (rdev->bios == NULL) + return tv_std; + tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); if (tv_info) { if (RBIOS8(tv_info + 6) == 'T') { -- cgit v1.2.3-70-g09d2 From 9270eb1b496cb002d75f49ef82c9ef4cbd22a5a0 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 13 Jan 2010 09:21:49 +1000 Subject: drm/radeon/kms: only evict to GTT if CP is ready Testing GTT ready might be more correct but cp.ready works fine and has been tested on irc by 2-3 ppl. fixes bug k.org 15035 and fd.o 25733 Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_ttm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index a00450743d6..db820ae9a03 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -215,7 +215,10 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, rbo = container_of(bo, struct radeon_bo, tbo); switch (bo->mem.mem_type) { case TTM_PL_VRAM: - radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); + if (rbo->rdev->cp.ready == false) + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); + else + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); break; case TTM_PL_TT: default: -- cgit v1.2.3-70-g09d2 From 70a94d6a35072b62f808155f117f00485a395f03 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 13 Jan 2010 16:15:11 +1000 Subject: drm: fix crtc no modes printf + typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Toralf Förster pointed out the typo, the fact I forget the if statement is purely personal fail. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc_helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 077313f0d47..1c47ea25337 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -1032,7 +1032,8 @@ bool drm_helper_initial_config(struct drm_device *dev) /* * we shouldn't end up with no modes here. */ - printk(KERN_INFO "No connectors reported conncted with modes\n"); + if (count == 0) + printk(KERN_INFO "No connectors reported connected with modes\n"); drm_setup_crtcs(dev); -- cgit v1.2.3-70-g09d2 From ef14587706521287f1c7ea3326e732f7d86dd096 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Wed, 13 Jan 2010 13:38:59 +0800 Subject: drm: change drm set mode messages as DRM_DEBUG Following drm info repeat 207 times during one hour, it's quite annoying [ 1266.286747] [drm] TV-19: set mode NTSC 480i 0 Change from DRM_INFO to DRM_DEBUG Signed-off-by: Dave Young Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 1c47ea25337..7d0f00a935f 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -702,7 +702,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; - DRM_INFO("%s: set mode %s %x\n", drm_get_encoder_name(encoder), + DRM_DEBUG("%s: set mode %s %x\n", drm_get_encoder_name(encoder), mode->name, mode->base.id); encoder_funcs = encoder->helper_private; encoder_funcs->mode_set(encoder, mode, adjusted_mode); -- cgit v1.2.3-70-g09d2 From 4a18b3ab6ed537b055e3fcfca64ab870b4f9acf0 Mon Sep 17 00:00:00 2001 From: Tai-hwa Liang Date: Wed, 13 Jan 2010 00:16:27 -0800 Subject: Input: pmouse - move Sentelic probe down the list Sentelic probes confuse IBM trackpoints so they stop responding to TP_READ_ID command. See: http://bugzilla.kernel.org/show_bug.cgi?id=14970 Let's move FSP detection lower so it is probed after trackpoint and others, just before we strat probing for Intellimouse Explorer. Signed-off-by: Tai-hwa Liang Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index cabf4e1caac..9774bdfaa48 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -690,19 +690,6 @@ static int psmouse_extensions(struct psmouse *psmouse, max_proto = PSMOUSE_IMEX; } -/* - * Try Finger Sensing Pad - */ - if (max_proto > PSMOUSE_IMEX) { - if (fsp_detect(psmouse, set_properties) == 0) { - if (!set_properties || fsp_init(psmouse) == 0) - return PSMOUSE_FSP; -/* - * Init failed, try basic relative protocols - */ - max_proto = PSMOUSE_IMEX; - } - } if (max_proto > PSMOUSE_IMEX) { if (genius_detect(psmouse, set_properties) == 0) @@ -718,6 +705,21 @@ static int psmouse_extensions(struct psmouse *psmouse, return PSMOUSE_TOUCHKIT_PS2; } +/* + * Try Finger Sensing Pad. We do it here because its probe upsets + * Trackpoint devices (causing TP_READ_ID command to time out). + */ + if (max_proto > PSMOUSE_IMEX) { + if (fsp_detect(psmouse, set_properties) == 0) { + if (!set_properties || fsp_init(psmouse) == 0) + return PSMOUSE_FSP; +/* + * Init failed, try basic relative protocols + */ + max_proto = PSMOUSE_IMEX; + } + } + /* * Reset to defaults in case the device got confused by extended * protocol probes. Note that we follow up with full reset because -- cgit v1.2.3-70-g09d2 From c332e9fcc5289698350d39d4d22c3ed5257d7a80 Mon Sep 17 00:00:00 2001 From: Tai-hwa Liang Date: Wed, 13 Jan 2010 00:25:35 -0800 Subject: Input: sentelic - fix left/right horizontal scroll mapping Signed-off-by: Tai-hwa Liang Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/sentelic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 77b9fd0b3fb..81a6b81cb2f 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -2,7 +2,7 @@ * Finger Sensing Pad PS/2 mouse driver. * * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. - * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation. + * Copyright (C) 2005-2010 Tai-hwa Liang, Sentelic Corporation. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -658,9 +658,9 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) if (packet[3] & BIT(1)) button_status |= 0x0f; /* wheel up */ if (packet[3] & BIT(2)) - button_status |= BIT(5);/* horizontal left */ + button_status |= BIT(4);/* horizontal left */ if (packet[3] & BIT(3)) - button_status |= BIT(4);/* horizontal right */ + button_status |= BIT(5);/* horizontal right */ /* push back to packet queue */ if (button_status != 0) packet[3] = button_status; -- cgit v1.2.3-70-g09d2 From f6a8c60960bbea378142d1fa1b3d111555ee41c7 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Sun, 29 Nov 2009 15:23:51 +0000 Subject: mtd: Really add ARM pismo support (Commit 7cb777a3d71f9d1f7eb149c7a504d21f24219ae8 (mtd: add ARM pismo support) intended to add this, but seems only to have patched the Makefile without touching Kconfig or providing any code...) The following patch adds support for PISMO modules found on ARM Ltd development platforms. These are MTD modules, and can have a selection of SRAM, flash or DOC devices as described by an on-board I2C EEPROM. We support SRAM and NOR flash devices only by registering appropriate conventional MTD platform devices as children of the 'pismo' device. Signed-off-by: Russell King Signed-off-by: David Woodhouse --- drivers/mtd/maps/Kconfig | 17 +++ drivers/mtd/maps/pismo.c | 320 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mtd/pismo.h | 17 +++ 3 files changed, 354 insertions(+) create mode 100644 drivers/mtd/maps/pismo.c create mode 100644 include/linux/mtd/pismo.h (limited to 'drivers') diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 4c364d44ad5..2de0cc823d6 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -549,4 +549,21 @@ config MTD_VMU To build this as a module select M here, the module will be called vmu-flash. +config MTD_PISMO + tristate "MTD discovery driver for PISMO modules" + depends on I2C + depends on ARCH_VERSATILE + help + This driver allows for discovery of PISMO modules - see + . These are small modules containing + up to five memory devices (eg, SRAM, flash, DOC) described by an + I2C EEPROM. + + This driver does not create any MTD maps itself; instead it + creates MTD physmap and MTD SRAM platform devices. If you + enable this option, you should consider enabling MTD_PHYSMAP + and/or MTD_PLATRAM according to the devices on your module. + + When built as a module, it will be called pismo.ko + endmenu diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c new file mode 100644 index 00000000000..c48cad271f5 --- /dev/null +++ b/drivers/mtd/maps/pismo.c @@ -0,0 +1,320 @@ +/* + * PISMO memory driver - http://www.pismoworld.org/ + * + * For ARM Realview and Versatile platforms + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PISMO_NUM_CS 5 + +struct pismo_cs_block { + u8 type; + u8 width; + __le16 access; + __le32 size; + u32 reserved[2]; + char device[32]; +} __packed; + +struct pismo_eeprom { + struct pismo_cs_block cs[PISMO_NUM_CS]; + char board[15]; + u8 sum; +} __packed; + +struct pismo_mem { + phys_addr_t base; + u32 size; + u16 access; + u8 width; + u8 type; +}; + +struct pismo_data { + struct i2c_client *client; + void (*vpp)(void *, int); + void *vpp_data; + struct platform_device *dev[PISMO_NUM_CS]; +}; + +/* FIXME: set_vpp could do with a better calling convention */ +static struct pismo_data *vpp_pismo; +static DEFINE_MUTEX(pismo_mutex); + +static int pismo_setvpp_probe_fix(struct pismo_data *pismo) +{ + mutex_lock(&pismo_mutex); + if (vpp_pismo) { + mutex_unlock(&pismo_mutex); + kfree(pismo); + return -EBUSY; + } + vpp_pismo = pismo; + mutex_unlock(&pismo_mutex); + return 0; +} + +static void pismo_setvpp_remove_fix(struct pismo_data *pismo) +{ + mutex_lock(&pismo_mutex); + if (vpp_pismo == pismo) + vpp_pismo = NULL; + mutex_unlock(&pismo_mutex); +} + +static void pismo_set_vpp(struct map_info *map, int on) +{ + struct pismo_data *pismo = vpp_pismo; + + pismo->vpp(pismo->vpp_data, on); +} +/* end of hack */ + + +static unsigned int __devinit pismo_width_to_bytes(unsigned int width) +{ + width &= 15; + if (width > 2) + return 0; + return 1 << width; +} + +static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf, + u8 addr, size_t size) +{ + int ret; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .len = sizeof(addr), + .buf = &addr, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = size, + .buf = buf, + }, + }; + + ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + + return ret == ARRAY_SIZE(msg) ? size : -EIO; +} + +static int __devinit pismo_add_device(struct pismo_data *pismo, int i, + struct pismo_mem *region, const char *name, void *pdata, size_t psize) +{ + struct platform_device *dev; + struct resource res = { }; + phys_addr_t base = region.base; + int ret; + + if (base == ~0) + return -ENXIO; + + res.start = base; + res.end = base + region->size - 1; + res.flags = IORESOURCE_MEM; + + dev = platform_device_alloc(name, i); + if (!dev) + return -ENOMEM; + dev->dev.parent = &pismo->client->dev; + + do { + ret = platform_device_add_resources(dev, &res, 1); + if (ret) + break; + + ret = platform_device_add_data(dev, pdata, psize); + if (ret) + break; + + ret = platform_device_add(dev); + if (ret) + break; + + pismo->dev[i] = dev; + return 0; + } while (0); + + platform_device_put(dev); + return ret; +} + +static int __devinit pismo_add_nor(struct pismo_data *pismo, int i, + struct pismo_mem *region) +{ + struct physmap_flash_data data = { + .width = region->width, + }; + + if (pismo->vpp) + data.set_vpp = pismo_set_vpp; + + return pismo_add_device(pismo, i, region, "physmap-flash", + &data, sizeof(data)); +} + +static int __devinit pismo_add_sram(struct pismo_data *pismo, int i, + struct pismo_mem *region) +{ + struct platdata_mtd_ram data = { + .bankwidth = region->width, + }; + + return pismo_add_device(pismo, i, region, "mtd-ram", + &data, sizeof(data)); +} + +static void __devinit pismo_add_one(struct pismo_data *pismo, int i, + const struct pismo_cs_block *cs, phys_addr_t base) +{ + struct device *dev = &pismo->client->dev; + struct pismo_mem region; + + region.base = base; + region.type = cs->type; + region.width = pismo_width_to_bytes(cs->width); + region.access = le16_to_cpu(cs->access); + region.size = le32_to_cpu(cs->size); + + if (region.width == 0) { + dev_err(dev, "cs%u: bad width: %02x, ignoring\n", i, cs->width); + return; + } + + /* + * FIXME: may need to the platforms memory controller here, but at + * the moment we assume that it has already been correctly setup. + * The memory controller can also tell us the base address as well. + */ + + dev_info(dev, "cs%u: %.32s: type %02x access %u00ps size %uK\n", + i, cs->device, region.type, region.access, region.size / 1024); + + switch (region.type) { + case 0: + break; + case 1: + /* static DOC */ + break; + case 2: + /* static NOR */ + pismo_add_nor(pismo, i, ®ion); + break; + case 3: + /* static RAM */ + pismo_add_sram(pismo, i, ®ion); + break; + } +} + +static int __devexit pismo_remove(struct i2c_client *client) +{ + struct pismo_data *pismo = i2c_get_clientdata(client); + int i; + + for (i = 0; i < ARRAY_SIZE(pismo->dev); i++) + platform_device_unregister(pismo->dev[i]); + + /* FIXME: set_vpp needs saner arguments */ + pismo_setvpp_remove_fix(pismo); + + kfree(pismo); + + return 0; +} + +static int __devinit pismo_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct pismo_pdata *pdata = client->dev.platform_data; + struct pismo_eeprom eeprom; + struct pismo_data *pismo; + int ret, i; + + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "functionality mismatch\n"); + return -EIO; + } + + pismo = kzalloc(sizeof(*pismo), GFP_KERNEL); + if (!pismo) + return -ENOMEM; + + /* FIXME: set_vpp needs saner arguments */ + ret = pismo_setvpp_probe_fix(pismo); + if (ret) + return ret; + + pismo->client = client; + if (pdata) { + pismo->vpp = pdata->set_vpp; + pismo->vpp_data = pdata->vpp_data; + } + i2c_set_clientdata(client, pismo); + + ret = pismo_eeprom_read(client, &eeprom, 0, sizeof(eeprom)); + if (ret < 0) { + dev_err(&client->dev, "error reading EEPROM: %d\n", ret); + return ret; + } + + dev_info(&client->dev, "%.15s board found\n", eeprom.board); + + for (i = 0; i < ARRAY_SIZE(eeprom.cs); i++) + if (eeprom.cs[i].type != 0xff) + pismo_add_one(pismo, i, &eeprom.cs[i], + pdata->cs_addrs[i]); + + return 0; +} + +static const struct i2c_device_id pismo_id[] = { + { "pismo" }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, pismo_id); + +static struct i2c_driver pismo_driver = { + .driver = { + .name = "pismo", + .owner = THIS_MODULE, + }, + .probe = pismo_probe, + .remove = __devexit_p(pismo_remove), + .id_table = pismo_id, +}; + +static int __init pismo_init(void) +{ + BUILD_BUG_ON(sizeof(struct pismo_cs_block) != 48); + BUILD_BUG_ON(sizeof(struct pismo_eeprom) != 256); + + return i2c_add_driver(&pismo_driver); +} +module_init(pismo_init); + +static void __exit pismo_exit(void) +{ + i2c_del_driver(&pismo_driver); +} +module_exit(pismo_exit); + +MODULE_AUTHOR("Russell King "); +MODULE_DESCRIPTION("PISMO memory driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mtd/pismo.h b/include/linux/mtd/pismo.h new file mode 100644 index 00000000000..8dfb7e1421c --- /dev/null +++ b/include/linux/mtd/pismo.h @@ -0,0 +1,17 @@ +/* + * PISMO memory driver - http://www.pismoworld.org/ + * + * 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. + */ +#ifndef __LINUX_MTD_PISMO_H +#define __LINUX_MTD_PISMO_H + +struct pismo_pdata { + void (*set_vpp)(void *, int); + void *vpp_data; + phys_addr_t cs_addrs[5]; +}; + +#endif -- cgit v1.2.3-70-g09d2 From f5e2bae0aad03164ffc7ce9dfeee6608e2c87dba Mon Sep 17 00:00:00 2001 From: Morten Thunberg Svendsen Date: Wed, 6 Jan 2010 10:48:18 +0100 Subject: mtd: tests: fix read, speed and stress tests on NOR flash Before using block_isbad() check if mtd->block_isbad() is defined. Calculating pgcnt must be done using pgsize defined to 512 on NOR and mtd->writesize for NAND, not using mtd->writesize directly. Signed-off-by: Morten Thunberg Svendsen Acked-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/tests/mtd_readtest.c | 6 +++++- drivers/mtd/tests/mtd_speedtest.c | 7 ++++++- drivers/mtd/tests/mtd_stresstest.c | 6 +++++- 3 files changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c index 79fc4530987..25c5dd03a83 100644 --- a/drivers/mtd/tests/mtd_readtest.c +++ b/drivers/mtd/tests/mtd_readtest.c @@ -147,6 +147,10 @@ static int scan_for_bad_eraseblocks(void) } memset(bbt, 0 , ebcnt); + /* NOR flash does not implement block_isbad */ + if (mtd->block_isbad == NULL) + return 0; + printk(PRINT_PREF "scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { bbt[i] = is_block_bad(i) ? 1 : 0; @@ -184,7 +188,7 @@ static int __init mtd_readtest_init(void) tmp = mtd->size; do_div(tmp, mtd->erasesize); ebcnt = tmp; - pgcnt = mtd->erasesize / mtd->writesize; + pgcnt = mtd->erasesize / pgsize; printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " "page size %u, count of eraseblocks %u, pages per " diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c index 141363a7e80..7fbb51d4eab 100644 --- a/drivers/mtd/tests/mtd_speedtest.c +++ b/drivers/mtd/tests/mtd_speedtest.c @@ -301,6 +301,10 @@ static int scan_for_bad_eraseblocks(void) } memset(bbt, 0 , ebcnt); + /* NOR flash does not implement block_isbad */ + if (mtd->block_isbad == NULL) + goto out; + printk(PRINT_PREF "scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { bbt[i] = is_block_bad(i) ? 1 : 0; @@ -309,6 +313,7 @@ static int scan_for_bad_eraseblocks(void) cond_resched(); } printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); +out: goodebcnt = ebcnt - bad; return 0; } @@ -340,7 +345,7 @@ static int __init mtd_speedtest_init(void) tmp = mtd->size; do_div(tmp, mtd->erasesize); ebcnt = tmp; - pgcnt = mtd->erasesize / mtd->writesize; + pgcnt = mtd->erasesize / pgsize; printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " "page size %u, count of eraseblocks %u, pages per " diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c index 63920476b57..a99d3cd737d 100644 --- a/drivers/mtd/tests/mtd_stresstest.c +++ b/drivers/mtd/tests/mtd_stresstest.c @@ -227,6 +227,10 @@ static int scan_for_bad_eraseblocks(void) } memset(bbt, 0 , ebcnt); + /* NOR flash does not implement block_isbad */ + if (mtd->block_isbad == NULL) + return 0; + printk(PRINT_PREF "scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { bbt[i] = is_block_bad(i) ? 1 : 0; @@ -265,7 +269,7 @@ static int __init mtd_stresstest_init(void) tmp = mtd->size; do_div(tmp, mtd->erasesize); ebcnt = tmp; - pgcnt = mtd->erasesize / mtd->writesize; + pgcnt = mtd->erasesize / pgsize; printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " "page size %u, count of eraseblocks %u, pages per " -- cgit v1.2.3-70-g09d2 From c5cae661d6cf808b6984762f763261adf35f3eb7 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 17 Dec 2009 13:57:09 +0000 Subject: xen: fix hang on suspend. In 65f63384 "xen: improve error handling in do_suspend" I said: - xs_suspend()/xs_resume() and dpm_suspend_noirq()/dpm_resume_noirq() were not nested in the obvious way. and changed the ordering of the calls as so: BEFORE AFTER xs_suspend dpm_suspend_noirq dpm_suspend_noirq xs_suspend *SUSPEND* *SUSPEND* dpm_resume_noirq dpm_resume_noirq xs_resume xs_resume Clearly this is not an improvement and I was talking rubbish. In particular the new ordering is susceptible to a hang if a xenstore write is in progress at the point at which the suspend kicks in. When the suspend process calls xs_suspend it tries to take the request_mutex but if a write is in progress it could be looping in xenbus_xs.c:read_reply() waiting for something to arrive on &xs_state.reply_list while holding the request_mutex (taken in the caller of read_reply). However if we have done dpm_suspend_noirq before xs_suspend then we won't get any more xenstore interrupts and process_msg() will never be woken up to add anything to the reply_list. Fix this by calling xs_suspend before dpm_suspend_noirq. If dpm_suspend_noirq fails then make sure we go through the xs_suspend_cancel() code path. Signed-off-by: Ian Campbell Acked-by: Jeremy Fitzhardinge Cc: Stable Kernel --- drivers/xen/manage.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index c4997930afc..5d42d55e299 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -102,15 +102,15 @@ static void do_suspend(void) goto out_thaw; } + printk(KERN_DEBUG "suspending xenstore...\n"); + xs_suspend(); + err = dpm_suspend_noirq(PMSG_SUSPEND); if (err) { printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err); goto out_resume; } - printk(KERN_DEBUG "suspending xenstore...\n"); - xs_suspend(); - err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); dpm_resume_noirq(PMSG_RESUME); @@ -120,13 +120,13 @@ static void do_suspend(void) cancelled = 1; } +out_resume: if (!cancelled) { xen_arch_resume(); xs_resume(); } else xs_suspend_cancel(); -out_resume: dpm_resume_end(PMSG_RESUME); /* Make sure timer events get retriggered on all CPUs */ -- cgit v1.2.3-70-g09d2 From 42590a75019a50012f25a962246498dead428433 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 4 Jan 2010 16:16:23 +0900 Subject: x86/agp: Fix agp_amd64_init and agp_amd64_cleanup This fixes the regression introduced by the commit f405d2c02395a74d3883bd03ded36457aa3697ad. The above commit fixes the following issue: http://marc.info/?l=linux-kernel&m=126192729110083&w=2 However, it doesn't work properly when you remove and insert the agp_amd64 module again. agp_amd64_init() and agp_amd64_cleanup should be called only when gart_iommu is not called earlier (that is, the GART IOMMU is not enabled). We need to use 'gart_iommu_aperture' to see if GART IOMMU is enabled or not. Signed-off-by: FUJITA Tomonori Cc: mitov@issp.bas.bg Cc: davej@redhat.com LKML-Reference: <20100104161603L.fujita.tomonori@lab.ntt.co.jp> Signed-off-by: Ingo Molnar --- arch/x86/kernel/aperture_64.c | 1 + drivers/char/agp/amd64-agp.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 3704997e8b2..f147a95fd84 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -31,6 +31,7 @@ #include int gart_iommu_aperture; +EXPORT_SYMBOL_GPL(gart_iommu_aperture); int gart_iommu_aperture_disabled __initdata; int gart_iommu_aperture_allowed __initdata; diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 5aa7a586a7f..1afb8968a34 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -725,12 +725,11 @@ static struct pci_driver agp_amd64_pci_driver = { int __init agp_amd64_init(void) { int err = 0; - static int done = 0; if (agp_off) return -EINVAL; - if (done++) + if (gart_iommu_aperture) return agp_bridges_found ? 0 : -ENODEV; err = pci_register_driver(&agp_amd64_pci_driver); @@ -771,6 +770,8 @@ int __init agp_amd64_init(void) static void __exit agp_amd64_cleanup(void) { + if (gart_iommu_aperture) + return; if (aperture_resource) release_resource(aperture_resource); pci_unregister_driver(&agp_amd64_pci_driver); -- cgit v1.2.3-70-g09d2 From d01799b2f399603ae4cecc06f6ea146c57519cb1 Mon Sep 17 00:00:00 2001 From: Przemo Firszt Date: Mon, 4 Jan 2010 12:32:00 +0100 Subject: HID: fix pad button definition in hid-wacom This fix is required for xorg driver to recognise 2 pad buttons Signed-off-by: Przemo Firszt Signed-off-by: Jiri Kosina --- drivers/hid/hid-wacom.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 74754217224..75ea66affb6 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -196,6 +196,9 @@ static int wacom_probe(struct hid_device *hdev, /* Pad */ input->evbit[0] |= BIT(EV_MSC); input->mscbit[0] |= BIT(MSC_SERIAL); + set_bit(BTN_0, input->keybit); + set_bit(BTN_1, input->keybit); + set_bit(BTN_TOOL_FINGER, input->keybit); /* Distance, rubber and mouse */ input->absbit[0] |= BIT(ABS_DISTANCE); -- cgit v1.2.3-70-g09d2 From 23aeb61e7e1f02fb0f3b8f9e798e75537ca1731d Mon Sep 17 00:00:00 2001 From: Christian Schuerer-Waldheim Date: Wed, 6 Jan 2010 14:49:57 +0100 Subject: HID: add device IDs for new model of Apple Wireless Keyboard Added device IDs for the new model of the Apple Wireless Keyboard (November 2009). Signed-off-by: Christian Schuerer-Waldheim Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 7 +++++++ drivers/hid/hid-core.c | 3 +++ drivers/hid/hid-ids.h | 3 +++ 3 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 4b96e7a898c..5b4d66dc1a0 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -431,6 +431,13 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | + APPLE_ISO_KEYBOARD }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 389cd5f0a68..eabe5f87c6c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1285,6 +1285,9 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b9de32b6b10..010368e649e 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -88,6 +88,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 -- cgit v1.2.3-70-g09d2 From 0e253fdb3b5739fd8514f617ec582762bcfaea48 Mon Sep 17 00:00:00 2001 From: Przemo Firszt Date: Sat, 9 Jan 2010 15:20:03 +0100 Subject: HID: wacom: Add BTN_TOOL_FINGER for pad button reporting Without this patch xf86-input-wacom driver wasn't able to properly recognise pad button events. It was also causing some problems with button mapping. Signed-off-by: Przemo Firszt Signed-off-by: Jiri Kosina --- drivers/hid/hid-wacom.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 75ea66affb6..12dcda52920 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -142,6 +142,7 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, wdata->butstate = rw; input_report_key(input, BTN_0, rw & 0x02); input_report_key(input, BTN_1, rw & 0x01); + input_report_key(input, BTN_TOOL_FINGER, 0xf0); input_event(input, EV_MSC, MSC_SERIAL, 0xf0); input_sync(input); } -- cgit v1.2.3-70-g09d2 From 880348653ec2eda81550a8aa37c2eb625922f695 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:29 +0100 Subject: [S390] dasd: add missing compat ptr conversion Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_ioctl.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 478bcdb90b6..fc7b30b4a25 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -17,7 +17,7 @@ #include #include #include - +#include #include #include #include @@ -358,9 +358,8 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp) } static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd, - unsigned long arg) + struct cmbdata __user *argp) { - struct cmbdata __user *argp = (void __user *) arg; size_t size = _IOC_SIZE(cmd); struct cmbdata data; int ret; @@ -376,7 +375,12 @@ dasd_do_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct dasd_block *block = bdev->bd_disk->private_data; - void __user *argp = (void __user *)arg; + void __user *argp; + + if (is_compat_task()) + argp = compat_ptr(arg); + else + argp = (void __user *)arg; if (!block) return -ENODEV; @@ -414,7 +418,7 @@ dasd_do_ioctl(struct block_device *bdev, fmode_t mode, case BIODASDCMFDISABLE: return disable_cmf(block->base->cdev); case BIODASDREADALLCMB: - return dasd_ioctl_readall_cmb(block, cmd, arg); + return dasd_ioctl_readall_cmb(block, cmd, argp); default: /* if the discipline has an ioctl method try it. */ if (block->base->discipline->ioctl) { -- cgit v1.2.3-70-g09d2 From 44ee6a8564a89a77206b0b13cea91fc2f4ff997d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:30 +0100 Subject: [S390] cio: add missing compat ptr conversion Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chsc_sch.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index cc5144b6f9d..c84ac944307 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -770,24 +771,30 @@ out_free: static long chsc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { + void __user *argp; + CHSC_MSG(2, "chsc_ioctl called, cmd=%x\n", cmd); + if (is_compat_task()) + argp = compat_ptr(arg); + else + argp = (void __user *)arg; switch (cmd) { case CHSC_START: - return chsc_ioctl_start((void __user *)arg); + return chsc_ioctl_start(argp); case CHSC_INFO_CHANNEL_PATH: - return chsc_ioctl_info_channel_path((void __user *)arg); + return chsc_ioctl_info_channel_path(argp); case CHSC_INFO_CU: - return chsc_ioctl_info_cu((void __user *)arg); + return chsc_ioctl_info_cu(argp); case CHSC_INFO_SCH_CU: - return chsc_ioctl_info_sch_cu((void __user *)arg); + return chsc_ioctl_info_sch_cu(argp); case CHSC_INFO_CI: - return chsc_ioctl_conf_info((void __user *)arg); + return chsc_ioctl_conf_info(argp); case CHSC_INFO_CCL: - return chsc_ioctl_conf_comp_list((void __user *)arg); + return chsc_ioctl_conf_comp_list(argp); case CHSC_INFO_CPD: - return chsc_ioctl_chpd((void __user *)arg); + return chsc_ioctl_chpd(argp); case CHSC_INFO_DCAL: - return chsc_ioctl_dcal((void __user *)arg); + return chsc_ioctl_dcal(argp); default: /* unknown ioctl number */ return -ENOIOCTLCMD; } -- cgit v1.2.3-70-g09d2 From 8f3eabe3835449117058efaf5e90f28bf030e859 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:31 +0100 Subject: [S390] vmcp: add missing compat ptr conversion Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/vmcp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index a6087cec55b..921dcda7767 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -139,21 +140,26 @@ vmcp_write(struct file *file, const char __user *buff, size_t count, static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct vmcp_session *session; + int __user *argp; int temp; session = (struct vmcp_session *)file->private_data; + if (is_compat_task()) + argp = compat_ptr(arg); + else + argp = (int __user *)arg; if (mutex_lock_interruptible(&session->mutex)) return -ERESTARTSYS; switch (cmd) { case VMCP_GETCODE: temp = session->resp_code; mutex_unlock(&session->mutex); - return put_user(temp, (int __user *)arg); + return put_user(temp, argp); case VMCP_SETBUF: free_pages((unsigned long)session->response, get_order(session->bufsize)); session->response=NULL; - temp = get_user(session->bufsize, (int __user *)arg); + temp = get_user(session->bufsize, argp); if (get_order(session->bufsize) > 8) { session->bufsize = PAGE_SIZE; temp = -EINVAL; @@ -163,7 +169,7 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case VMCP_GETSIZE: temp = session->resp_size; mutex_unlock(&session->mutex); - return put_user(temp, (int __user *)arg); + return put_user(temp, argp); default: mutex_unlock(&session->mutex); return -ENOIOCTLCMD; -- cgit v1.2.3-70-g09d2 From 16e1a577693a470367287281765b7daad0998fc1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:32 +0100 Subject: [S390] fs3270: add missing compat ptr conversion Add missing compat ptr conversion including two additional whitespace changes that aren't worth a separate patch. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/fs3270.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 247b2b93472..31c59b0d6df 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -322,6 +323,7 @@ fs3270_write(struct file *filp, const char __user *data, size_t count, loff_t *o static long fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { + char __user *argp; struct fs3270 *fp; struct raw3270_iocb iocb; int rc; @@ -329,6 +331,10 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) fp = filp->private_data; if (!fp) return -ENODEV; + if (is_compat_task()) + argp = compat_ptr(arg); + else + argp = (char __user *)arg; rc = 0; mutex_lock(&fs3270_mutex); switch (cmd) { @@ -339,10 +345,10 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) fp->write_command = arg; break; case TUBGETI: - rc = put_user(fp->read_command, (char __user *) arg); + rc = put_user(fp->read_command, argp); break; case TUBGETO: - rc = put_user(fp->write_command,(char __user *) arg); + rc = put_user(fp->write_command, argp); break; case TUBGETMOD: iocb.model = fp->view.model; @@ -351,8 +357,7 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) iocb.pf_cnt = 24; iocb.re_cnt = 20; iocb.map = 0; - if (copy_to_user((char __user *) arg, &iocb, - sizeof(struct raw3270_iocb))) + if (copy_to_user(argp, &iocb, sizeof(struct raw3270_iocb))) rc = -EFAULT; break; } @@ -511,8 +516,8 @@ static const struct file_operations fs3270_fops = { .write = fs3270_write, /* write */ .unlocked_ioctl = fs3270_ioctl, /* ioctl */ .compat_ioctl = fs3270_ioctl, /* ioctl */ - .open = fs3270_open, /* open */ - .release = fs3270_close, /* release */ + .open = fs3270_open, /* open */ + .release = fs3270_close, /* release */ }; /* -- cgit v1.2.3-70-g09d2 From 957a37ad587f3ef1022f1fe434d818cbed38eb95 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:36 +0100 Subject: [S390] tape_block: remove ioctl function This is just a complicated construct which always returns -EINVAL. Just remove it. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tape_block.c | 39 --------------------------------------- 1 file changed, 39 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 96816149368..8d3d720737d 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -46,8 +46,6 @@ */ static int tapeblock_open(struct block_device *, fmode_t); static int tapeblock_release(struct gendisk *, fmode_t); -static int tapeblock_ioctl(struct block_device *, fmode_t, unsigned int, - unsigned long); static int tapeblock_medium_changed(struct gendisk *); static int tapeblock_revalidate_disk(struct gendisk *); @@ -55,7 +53,6 @@ static const struct block_device_operations tapeblock_fops = { .owner = THIS_MODULE, .open = tapeblock_open, .release = tapeblock_release, - .ioctl = tapeblock_ioctl, .media_changed = tapeblock_medium_changed, .revalidate_disk = tapeblock_revalidate_disk, }; @@ -415,42 +412,6 @@ tapeblock_release(struct gendisk *disk, fmode_t mode) return 0; } -/* - * Support of some generic block device IOCTLs. - */ -static int -tapeblock_ioctl( - struct block_device * bdev, - fmode_t mode, - unsigned int command, - unsigned long arg -) { - int rc; - int minor; - struct gendisk *disk = bdev->bd_disk; - struct tape_device *device; - - rc = 0; - BUG_ON(!disk); - device = disk->private_data; - BUG_ON(!device); - minor = MINOR(bdev->bd_dev); - - DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command); - DBF_LH(6, "device = %d:%d\n", tapeblock_major, minor); - - switch (command) { - /* Refuse some IOCTL calls without complaining (mount). */ - case 0x5310: /* CDROMMULTISESSION */ - rc = -EINVAL; - break; - default: - rc = -EINVAL; - } - - return rc; -} - /* * Initialize block device frontend. */ -- cgit v1.2.3-70-g09d2 From f8b068593db4a4184c8963fcd5a7f34584fde8ad Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:40 +0100 Subject: [S390] dasd: add proper compat pointer conversion for symmetrix ioctl Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eckd.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 5819dc02a14..1c500c46222 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -2844,13 +2845,16 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) rc = -EFAULT; if (copy_from_user(&usrparm, argp, sizeof(usrparm))) goto out; -#ifndef CONFIG_64BIT - /* Make sure pointers are sane even on 31 bit. */ - if ((usrparm.psf_data >> 32) != 0 || (usrparm.rssd_result >> 32) != 0) { + if (is_compat_task() || sizeof(long) == 4) { + /* Make sure pointers are sane even on 31 bit. */ rc = -EINVAL; - goto out; + if ((usrparm.psf_data >> 32) != 0) + goto out; + if ((usrparm.rssd_result >> 32) != 0) + goto out; + usrparm.psf_data &= 0x7fffffffULL; + usrparm.rssd_result &= 0x7fffffffULL; } -#endif /* alloc I/O data area */ psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA); rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA); -- cgit v1.2.3-70-g09d2 From 7b475d59a07cb193310afae48367bd1ea2faa411 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:41 +0100 Subject: [S390] con3215: remove empty ioctl function ...instead of adding a compat ioctl function which would do nothing as well. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/con3215.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 9d61683b563..59ec073724b 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -1036,22 +1036,6 @@ static void tty3215_flush_buffer(struct tty_struct *tty) tty_wakeup(tty); } -/* - * Currently we don't have any io controls for 3215 ttys - */ -static int tty3215_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - switch (cmd) { - default: - return -ENOIOCTLCMD; - } - return 0; -} - /* * Disable reading from a 3215 tty */ @@ -1117,7 +1101,6 @@ static const struct tty_operations tty3215_ops = { .write_room = tty3215_write_room, .chars_in_buffer = tty3215_chars_in_buffer, .flush_buffer = tty3215_flush_buffer, - .ioctl = tty3215_ioctl, .throttle = tty3215_throttle, .unthrottle = tty3215_unthrottle, .stop = tty3215_stop, -- cgit v1.2.3-70-g09d2 From 0648f5659e2d51659bd8f42ff30f456775c3c12d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:43 +0100 Subject: [S390] zcrypt: add sanity check before copy_from_user() It's not obvious that copy_from_user() is called with a sane length parameter here. Even though it currently seems to be correct better add a check to prevent stack corruption / exploits. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/zcrypt_api.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 0d4d18bdd45..c68be24e27d 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -393,10 +393,12 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt) * u_mult_inv > 128 bytes. */ if (copied == 0) { - int len; + unsigned int len; spin_unlock_bh(&zcrypt_device_lock); /* len is max 256 / 2 - 120 = 8 */ len = crt->inputdatalength / 2 - 120; + if (len > sizeof(z1)) + return -EFAULT; z1 = z2 = z3 = 0; if (copy_from_user(&z1, crt->np_prime, len) || copy_from_user(&z2, crt->bp_key, len) || -- cgit v1.2.3-70-g09d2 From c5406079780f0f687316732353f49c3357504428 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:44 +0100 Subject: [S390] tape_char: add missing compat_ptr conversion Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tape_char.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index 2125ec7d95f..539045acaad 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -37,8 +38,9 @@ static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t static int tapechar_open(struct inode *,struct file *); static int tapechar_release(struct inode *,struct file *); static long tapechar_ioctl(struct file *, unsigned int, unsigned long); -static long tapechar_compat_ioctl(struct file *, unsigned int, - unsigned long); +#ifdef CONFIG_COMPAT +static long tapechar_compat_ioctl(struct file *, unsigned int, unsigned long); +#endif static const struct file_operations tape_fops = { @@ -46,7 +48,9 @@ static const struct file_operations tape_fops = .read = tapechar_read, .write = tapechar_write, .unlocked_ioctl = tapechar_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = tapechar_compat_ioctl, +#endif .open = tapechar_open, .release = tapechar_release, }; @@ -457,15 +461,22 @@ tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data) return rc; } +#ifdef CONFIG_COMPAT static long tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) { struct tape_device *device = filp->private_data; int rval = -ENOIOCTLCMD; + unsigned long argp; + /* The 'arg' argument of any ioctl function may only be used for + * pointers because of the compat pointer conversion. + * Consider this when adding new ioctls. + */ + argp = (unsigned long) compat_ptr(data); if (device->discipline->ioctl_fn) { mutex_lock(&device->mutex); - rval = device->discipline->ioctl_fn(device, no, data); + rval = device->discipline->ioctl_fn(device, no, argp); mutex_unlock(&device->mutex); if (rval == -EINVAL) rval = -ENOIOCTLCMD; @@ -473,6 +484,7 @@ tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) return rval; } +#endif /* CONFIG_COMPAT */ /* * Initialize character device frontend. -- cgit v1.2.3-70-g09d2 From 1a647bd213d85c88507967104aea79b2649e6a6e Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 13 Jan 2010 01:49:13 +0000 Subject: ixgbe: Do not attempt to perform interrupts in netpoll when down This patch resolves issues seen when running netconsole and rebooting via reboot -f. The issue was due to the fact that we were attempting to perform interrupt actions when the q_vectors and rings had already been freed via the ixgbe_shutdown routines. Signed-off-by: Alexander Duyck Acked-by: Mallikarjuna R Chilakala Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 2ad754c864c..385976709e7 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -5576,6 +5576,10 @@ static void ixgbe_netpoll(struct net_device *netdev) struct ixgbe_adapter *adapter = netdev_priv(netdev); int i; + /* if interface is down do nothing */ + if (test_bit(__IXGBE_DOWN, &adapter->state)) + return; + adapter->flags |= IXGBE_FLAG_IN_NETPOLL; if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; -- cgit v1.2.3-70-g09d2 From 8c47eaa76600cebc4869a42abb4568925ade6c47 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 13 Jan 2010 01:49:34 +0000 Subject: ixgbe: update copyright dates Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/Makefile | 2 +- drivers/net/ixgbe/ixgbe.h | 2 +- drivers/net/ixgbe/ixgbe_82598.c | 2 +- drivers/net/ixgbe/ixgbe_82599.c | 2 +- drivers/net/ixgbe/ixgbe_common.c | 2 +- drivers/net/ixgbe/ixgbe_common.h | 2 +- drivers/net/ixgbe/ixgbe_dcb.c | 2 +- drivers/net/ixgbe/ixgbe_dcb.h | 2 +- drivers/net/ixgbe/ixgbe_dcb_82598.c | 2 +- drivers/net/ixgbe/ixgbe_dcb_82598.h | 2 +- drivers/net/ixgbe/ixgbe_dcb_82599.c | 2 +- drivers/net/ixgbe/ixgbe_dcb_82599.h | 2 +- drivers/net/ixgbe/ixgbe_dcb_nl.c | 2 +- drivers/net/ixgbe/ixgbe_ethtool.c | 2 +- drivers/net/ixgbe/ixgbe_fcoe.c | 2 +- drivers/net/ixgbe/ixgbe_fcoe.h | 2 +- drivers/net/ixgbe/ixgbe_main.c | 4 ++-- drivers/net/ixgbe/ixgbe_phy.c | 2 +- drivers/net/ixgbe/ixgbe_phy.h | 2 +- drivers/net/ixgbe/ixgbe_type.h | 2 +- 20 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile index 21b41f42b61..bfef0ebcba9 100644 --- a/drivers/net/ixgbe/Makefile +++ b/drivers/net/ixgbe/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel 10 Gigabit PCI Express Linux driver -# Copyright(c) 1999 - 2009 Intel Corporation. +# Copyright(c) 1999 - 2010 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 8da8eb53508..303e7bd39b6 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 204177d78ce..3103f416531 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 538340527aa..b49bd6b9feb 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 688b8ca5da3..21f158f79dd 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index 27f3214bed2..dfff0ffaa50 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c index a1562287342..9aea4f04bbd 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.c +++ b/drivers/net/ixgbe/ixgbe_dcb.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h index 64a9fa15c05..5caafd4afbc 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.h +++ b/drivers/net/ixgbe/ixgbe_dcb.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c index f30263898eb..f0e9279d466 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ixgbe/ixgbe_dcb_82598.h index ebbe53c352a..cc728fa092e 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.h +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c index ec8a252636d..4f7a26ab411 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ixgbe/ixgbe_dcb_82599.h index 9e5e2827e4a..0f3f791e1e1 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.h +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 3c7a79a7d7c..56f37f66b69 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 0bd49d3b9f6..d77961fc75f 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index da32a108a7b..e9a20c88c15 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h index de8ff53187d..abf4b2b3f25 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.h +++ b/drivers/net/ixgbe/ixgbe_fcoe.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 385976709e7..9c9202f40b1 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -52,7 +52,7 @@ static const char ixgbe_driver_string[] = #define DRV_VERSION "2.0.44-k2" const char ixgbe_driver_version[] = DRV_VERSION; -static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation."; +static char ixgbe_copyright[] = "Copyright (c) 1999-2010 Intel Corporation."; static const struct ixgbe_info *ixgbe_info_tbl[] = { [board_82598] = &ixgbe_82598_info, diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 9ecad17522c..1c1efd38695 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h index 9b700f5bf1e..9cf5f3b4cc5 100644 --- a/drivers/net/ixgbe/ixgbe_phy.h +++ b/drivers/net/ixgbe/ixgbe_phy.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 84650c6ebe0..9eafddfa1b9 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, -- cgit v1.2.3-70-g09d2 From fddaa1aff881c98f524221236af98ce70dcd04cf Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 13 Jan 2010 01:52:49 +0000 Subject: e1000e: MDIO slow mode should always be done for 82577 A previous 82577 workaround that set the MDIO access speed to slow mode for every PHY register read/write when the cable is unplugged should instead set the access mode to always be slow before any PHY register access. Since the mode bit gets cleared when the PHY is reset, set the mode after every PHY reset. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/e1000.h | 1 - drivers/net/e1000e/ich8lan.c | 57 ++++++++++++++++++++++++++--- drivers/net/e1000e/phy.c | 85 -------------------------------------------- 3 files changed, 53 insertions(+), 90 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index cebbd9079d5..d6ee28f6ea0 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -582,7 +582,6 @@ extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data); -extern s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow); extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw); extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); extern s32 e1000_check_polarity_82577(struct e1000_hw *hw); diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index ad08cf3f40c..c2ea8619750 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -138,6 +138,10 @@ #define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ #define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ +/* KMRN Mode Control */ +#define HV_KMRN_MODE_CTRL PHY_REG(769, 16) +#define HV_KMRN_MDIO_SLOW 0x0400 + /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ /* Offset 04h HSFSTS */ union ich8_hws_flash_status { @@ -219,6 +223,7 @@ static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); +static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) { @@ -270,7 +275,21 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->id = e1000_phy_unknown; - e1000e_get_phy_id(hw); + ret_val = e1000e_get_phy_id(hw); + if (ret_val) + goto out; + if ((phy->id == 0) || (phy->id == PHY_REVISION_MASK)) { + /* + * In case the PHY needs to be in mdio slow mode (eg. 82577), + * set slow mode and try to get the PHY id again. + */ + ret_val = e1000_set_mdio_slow_mode_hv(hw); + if (ret_val) + goto out; + ret_val = e1000e_get_phy_id(hw); + if (ret_val) + goto out; + } phy->type = e1000e_get_phy_type_from_id(phy->id); switch (phy->type) { @@ -292,6 +311,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) break; } +out: return ret_val; } @@ -1075,6 +1095,26 @@ out: } +/** + * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode + * @hw: pointer to the HW structure + **/ +static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw) +{ + s32 ret_val; + u16 data; + + ret_val = e1e_rphy(hw, HV_KMRN_MODE_CTRL, &data); + if (ret_val) + return ret_val; + + data |= HV_KMRN_MDIO_SLOW; + + ret_val = e1e_wphy(hw, HV_KMRN_MODE_CTRL, data); + + return ret_val; +} + /** * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be * done after every PHY reset. @@ -1086,6 +1126,13 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) if (hw->mac.type != e1000_pchlan) return ret_val; + /* Set MDIO slow mode before any other MDIO access */ + if (hw->phy.type == e1000_phy_82577) { + ret_val = e1000_set_mdio_slow_mode_hv(hw); + if (ret_val) + goto out; + } + if (((hw->phy.type == e1000_phy_82577) && ((hw->phy.revision == 1) || (hw->phy.revision == 2))) || ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) { @@ -1184,6 +1231,7 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) /* Allow time for h/w to get to a quiescent state after reset */ mdelay(10); + /* Perform any necessary post-reset workarounds */ if (hw->mac.type == e1000_pchlan) { ret_val = e1000_hv_phy_workarounds_ich8lan(hw); if (ret_val) @@ -2484,6 +2532,10 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) if (!ret_val) e1000_release_swflag_ich8lan(hw); + /* Perform any necessary post-reset workarounds */ + if (hw->mac.type == e1000_pchlan) + ret_val = e1000_hv_phy_workarounds_ich8lan(hw); + if (ctrl & E1000_CTRL_PHY_RST) ret_val = hw->phy.ops.get_cfg_done(hw); @@ -2528,9 +2580,6 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) kab |= E1000_KABGTXD_BGSQLBIAS; ew32(KABGTXD, kab); - if (hw->mac.type == e1000_pchlan) - ret_val = e1000_hv_phy_workarounds_ich8lan(hw); - out: return ret_val; } diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 55a2c0acfee..7f3ceb9dad6 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -152,32 +152,9 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw) if (phy->id != 0 && phy->id != PHY_REVISION_MASK) goto out; - /* - * If the PHY ID is still unknown, we may have an 82577 - * without link. We will try again after setting Slow MDIC - * mode. No harm in trying again in this case since the PHY - * ID is unknown at this point anyway. - */ - ret_val = phy->ops.acquire(hw); - if (ret_val) - goto out; - ret_val = e1000_set_mdio_slow_mode_hv(hw, true); - if (ret_val) - goto out; - phy->ops.release(hw); - retry_count++; } out: - /* Revert to MDIO fast mode, if applicable */ - if (retry_count) { - ret_val = phy->ops.acquire(hw); - if (ret_val) - return ret_val; - ret_val = e1000_set_mdio_slow_mode_hv(hw, false); - phy->ops.release(hw); - } - return ret_val; } @@ -2790,38 +2767,6 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) return 0; } -/** - * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode - * @hw: pointer to the HW structure - * @slow: true for slow mode, false for normal mode - * - * Assumes semaphore already acquired. - **/ -s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow) -{ - s32 ret_val = 0; - u16 data = 0; - - /* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */ - hw->phy.addr = 1; - ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); - if (ret_val) - goto out; - - ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1, - (0x2180 | (slow << 10))); - if (ret_val) - goto out; - - /* dummy read when reverting to fast mode - throw away result */ - if (!slow) - ret_val = e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data); - -out: - return ret_val; -} - /** * __e1000_read_phy_reg_hv - Read HV PHY register * @hw: pointer to the HW structure @@ -2839,7 +2784,6 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, s32 ret_val; u16 page = BM_PHY_REG_PAGE(offset); u16 reg = BM_PHY_REG_NUM(offset); - bool in_slow_mode = false; if (!locked) { ret_val = hw->phy.ops.acquire(hw); @@ -2847,16 +2791,6 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, return ret_val; } - /* Workaround failure in MDIO access while cable is disconnected */ - if ((hw->phy.type == e1000_phy_82577) && - !(er32(STATUS) & E1000_STATUS_LU)) { - ret_val = e1000_set_mdio_slow_mode_hv(hw, true); - if (ret_val) - goto out; - - in_slow_mode = true; - } - /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, @@ -2893,10 +2827,6 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data); out: - /* Revert to MDIO fast mode, if applicable */ - if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) - ret_val |= e1000_set_mdio_slow_mode_hv(hw, false); - if (!locked) hw->phy.ops.release(hw); @@ -2948,7 +2878,6 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, s32 ret_val; u16 page = BM_PHY_REG_PAGE(offset); u16 reg = BM_PHY_REG_NUM(offset); - bool in_slow_mode = false; if (!locked) { ret_val = hw->phy.ops.acquire(hw); @@ -2956,16 +2885,6 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, return ret_val; } - /* Workaround failure in MDIO access while cable is disconnected */ - if ((hw->phy.type == e1000_phy_82577) && - !(er32(STATUS) & E1000_STATUS_LU)) { - ret_val = e1000_set_mdio_slow_mode_hv(hw, true); - if (ret_val) - goto out; - - in_slow_mode = true; - } - /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, @@ -3019,10 +2938,6 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, data); out: - /* Revert to MDIO fast mode, if applicable */ - if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) - ret_val |= e1000_set_mdio_slow_mode_hv(hw, false); - if (!locked) hw->phy.ops.release(hw); -- cgit v1.2.3-70-g09d2 From baf86c9d36826fab0160251bbc87dfab3af48a21 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 13 Jan 2010 01:53:08 +0000 Subject: e1000e: workaround link issues on busy hub in half duplex on 82577/82578 This patch removes a delay in hardware after every received packet allowing more time for transmitted packets to go out in between received packets in half duplex. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ich8lan.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index c2ea8619750..8b6ecd12788 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -1122,6 +1122,7 @@ static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw) static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) { s32 ret_val = 0; + u16 phy_data; if (hw->mac.type != e1000_pchlan) return ret_val; @@ -1165,16 +1166,32 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) hw->phy.addr = 1; ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); + hw->phy.ops.release(hw); if (ret_val) goto out; - hw->phy.ops.release(hw); /* * Configure the K1 Si workaround during phy reset assuming there is * link so that it disables K1 if link is in 1Gbps. */ ret_val = e1000_k1_gig_workaround_hv(hw, true); + if (ret_val) + goto out; + /* Workaround for link disconnects on a busy hub in half duplex */ + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + ret_val = hw->phy.ops.read_reg_locked(hw, + PHY_REG(BM_PORT_CTRL_PAGE, 17), + &phy_data); + if (ret_val) + goto release; + ret_val = hw->phy.ops.write_reg_locked(hw, + PHY_REG(BM_PORT_CTRL_PAGE, 17), + phy_data & 0x00FF); +release: + hw->phy.ops.release(hw); out: return ret_val; } -- cgit v1.2.3-70-g09d2 From 55029c1d65158aea9672c5dfadb43a57f23e3100 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 13 Jan 2010 04:34:25 +0000 Subject: sfc: Fix polling for slow MCDI operations When the interface is down and we are using polled mode for MCDI operations, we busy-wait for completion for approximately 1 jiffy using udelay() and then back off to schedule(). But the completion will not wake the task, since we are using polled mode! We must use schedule_timeout_uninterruptible() instead. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/mcdi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c index 683353b904c..0d4eba7266e 100644 --- a/drivers/net/sfc/mcdi.c +++ b/drivers/net/sfc/mcdi.c @@ -142,8 +142,9 @@ static int efx_mcdi_poll(struct efx_nic *efx) if (spins != 0) { --spins; udelay(1); - } else - schedule(); + } else { + schedule_timeout_uninterruptible(1); + } time = get_seconds(); -- cgit v1.2.3-70-g09d2 From f3766c26a5d00189e5c0965c66f01956d15a92d6 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 13 Jan 2010 10:59:13 +0000 Subject: sfc: Fix conditions for MDIO self-test The MDIO self-test should not be run on boards without an MDIO PHY, such as SFN5122F-R3 and later revisions. It should also not try to address a specific MMD in an MDIO clause 22 PHY. Check the mode_support field to decide which mode to use, if any. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/selftest.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index af393357979..250c8827b84 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c @@ -79,10 +79,14 @@ struct efx_loopback_state { static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests) { int rc = 0; - int devad = __ffs(efx->mdio.mmds); + int devad; u16 physid1, physid2; - if (efx->phy_type == PHY_TYPE_NONE) + if (efx->mdio.mode_support & MDIO_SUPPORTS_C45) + devad = __ffs(efx->mdio.mmds); + else if (efx->mdio.mode_support & MDIO_SUPPORTS_C22) + devad = MDIO_DEVAD_NONE; + else return 0; mutex_lock(&efx->mac_lock); -- cgit v1.2.3-70-g09d2 From 13fa95b0398d65885a79c6e95a09976ee9f8c009 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 12 Jan 2010 10:11:36 +0000 Subject: tg3: Fix std prod ring nicaddr for 5787 and 57765 Commit 87668d352aa8d135bd695a050f18bbfc7b50b506, titled "tg3: Don't touch RCB nic addresses", tried to avoid assigning the nic address of the standard producer ring. Unfortunately, the default nic address is not correct for the 5787, the 5755M, or the 57765. This patch reenables the old behavior and opts out of the assignment only for the 5717. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Tested-by: Chow Loong Jin Tested-by: Dmitry Torokhov Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 3a74d216859..5c77e6a4870 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7742,7 +7742,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ((u64) tpr->rx_std_mapping >> 32)); tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, ((u64) tpr->rx_std_mapping & 0xffffffff)); - if (!(tp->tg3_flags3 & TG3_FLG3_5755_PLUS)) + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC); -- cgit v1.2.3-70-g09d2 From 86cfe4ff02a51294cb2c974a8bedc7f648491df9 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 12 Jan 2010 10:11:37 +0000 Subject: tg3: Fix std rx prod ring handling There are some tg3 devices that require the driver to post new rx buffers in smaller increments. Commit 4361935afe3abc3e5a93006b99197fac1fabbd50, "tg3: Consider rx_std_prod_idx a hw mailbox" changed how the driver tracks the rx producer ring updates, but it does not make any special considerations for the above-mentioned devices. For those devices, it is possible for the driver to hit the special case path, which updates the hardware mailbox register but skips updating the shadow software mailbox member. If the special case path represents the final mailbox update for this ISR iteration, the hardware and software mailbox values will be out of sync. Ultimately, this will cause the driver to use a stale mailbox value on the next iteration, which will appear to the hardware as a large rx buffer update. Bad things ensue. The fix is to update the software shadow mailbox member when the special case path is taken. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reported-by: Dmitry Torokhov Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 5c77e6a4870..4e8b87d1ffa 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4693,8 +4693,9 @@ next_pkt: (*post_ptr)++; if (unlikely(rx_std_posted >= tp->rx_std_max_post)) { - u32 idx = *post_ptr % TG3_RX_RING_SIZE; - tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx); + tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE; + tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, + tpr->rx_std_prod_idx); work_mask &= ~RXD_OPAQUE_RING_STD; rx_std_posted = 0; } -- cgit v1.2.3-70-g09d2 From d1ec96af77df611d1728f3bb70289f83a02df1ea Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 12 Jan 2010 10:11:38 +0000 Subject: tg3: Add reliable serdes detection for 5717 A0 The serdes status bit does not work as intended for the 5717 A0. This patch implements an alternative detection scheme that will only be valid for A0 revisions. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 9 +++++++-- drivers/net/tg3.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4e8b87d1ffa..0a632f96d16 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1037,7 +1037,11 @@ static void tg3_mdio_start(struct tg3 *tp) else tp->phy_addr = 1; - is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES; + if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) + is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES; + else + is_serdes = tr32(TG3_CPMU_PHY_STRAP) & + TG3_CPMU_PHY_STRAP_IS_SERDES; if (is_serdes) tp->phy_addr += 7; } else @@ -12123,7 +12127,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->phy_id = eeprom_phy_id; if (eeprom_phy_serdes) { - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) tp->tg3_flags2 |= TG3_FLG2_MII_SERDES; else tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index cd30889650f..43ed41b9f55 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1054,6 +1054,8 @@ #define CPMU_MUTEX_REQ_DRIVER 0x00001000 #define TG3_CPMU_MUTEX_GNT 0x00003660 #define CPMU_MUTEX_GNT_DRIVER 0x00001000 +#define TG3_CPMU_PHY_STRAP 0x00003664 +#define TG3_CPMU_PHY_STRAP_IS_SERDES 0x00000020 /* 0x3664 --> 0x3800 unused */ /* Mbuf cluster free registers */ -- cgit v1.2.3-70-g09d2 From 55dffe79b34e2af98bd1315f1e00c2fc6a7a7078 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 12 Jan 2010 10:11:39 +0000 Subject: tg3: Disable 5717 serdes and B0 support The B0 revision of the 5717 will not get enough testing by the time 2.6.33 ships. Since the kernel is already at RC3, serdes support will require too many patches to fix. For these reasons, this patch disables 5717 serdes support and will refuse to attach to all 5717 devices that are later than an A0 revision. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0a632f96d16..2d1a7404057 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -13390,6 +13390,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (err) return err; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 && + (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0 || + (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) + return -ENOTSUPP; + /* Initialize data/descriptor byte/word swapping. */ val = tr32(GRC_MODE); val &= GRC_MODE_HOST_STACKUP; -- cgit v1.2.3-70-g09d2 From ba5b0bfa06b6fbee03c6889046e9adcefa5d2c20 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 12 Jan 2010 10:11:40 +0000 Subject: tg3: Update copyright and driver version This patch updates the copyright notice for 2010 and updates the version number to 3.106. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 6 +++--- drivers/net/tg3.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 2d1a7404057..7f82b0238e0 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4,7 +4,7 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. - * Copyright (C) 2005-2009 Broadcom Corporation. + * Copyright (C) 2005-2010 Broadcom Corporation. * * Firmware is: * Derived from proprietary unpublished source code, @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.105" -#define DRV_MODULE_RELDATE "December 2, 2009" +#define DRV_MODULE_VERSION "3.106" +#define DRV_MODULE_RELDATE "January 12, 2010" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 43ed41b9f55..8a167912902 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -4,6 +4,7 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. + * Copyright (C) 2007-2010 Broadcom Corporation. */ #ifndef _T3_H -- cgit v1.2.3-70-g09d2 From 7a15cbd40108a670baae71cbd3cec62b65891fa6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Jan 2010 11:42:17 +1000 Subject: drm/radeon/kms: fix displayport->dvi connector DDC. It appears that attempting AUXCH DDC breaks the subsequent attempt to do DDC over the i2c lines, so use the sink type to determine if we should be doing AUXCH or i2c DDC. This fixes my DVI monitor plugged into DP->DVI convertor. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 0ec491ead2f..47ceae9cdc4 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -357,7 +357,8 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; - if (dig->dp_i2c_bus) + if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || + dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus) radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter); } if (!radeon_connector->ddc_bus) -- cgit v1.2.3-70-g09d2 From 6398d42454ce1671b3422c34fd0f600c9c76c8b1 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 13 Jan 2010 12:32:36 +0100 Subject: drm/radeon/kms: Do not unpin buffer in fb destruction It's not necessary to unpin buffer in fb destruction. pin/unpin need to be balanced and we don't pin in fb creation. We pin when an fb is associated to a crtc and unpin when the fb is disassociated from the crtc. Note: Maybe we should take reference on fb in set_base callback so fb doesn't disappear until it's unbind from ctrc. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_display.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 47ceae9cdc4..49f3c69cf24 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -668,7 +668,6 @@ static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) radeonfb_remove(dev, fb); if (radeon_fb->obj) { - radeon_gem_object_unpin(radeon_fb->obj); mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(radeon_fb->obj); mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3-70-g09d2 From 30d2d9a54d48e4fefede0389ded1b6fc2d44a522 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 13 Jan 2010 10:29:27 +0100 Subject: drm/radeon/kms: Fix r600 blit cleanup path r600 blit cleanup path need to check if a bo was allocated before trying to free or unpin it. This patch add this check and avoid oops when the initialization on r6xx or r7xx hw fails. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 12 +++++++----- drivers/gpu/drm/radeon/r600_blit_kms.c | 14 ++++++++------ drivers/gpu/drm/radeon/rv770.c | 10 ++++++---- 3 files changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 9757962146f..3e02dd403d7 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1961,11 +1961,13 @@ int r600_suspend(struct radeon_device *rdev) r600_wb_disable(rdev); r600_pcie_gart_disable(rdev); /* unpin shaders bo */ - r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); - if (unlikely(r != 0)) - return r; - radeon_bo_unpin(rdev->r600_blit.shader_obj); - radeon_bo_unreserve(rdev->r600_blit.shader_obj); + if (rdev->r600_blit.shader_obj) { + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (!r) { + radeon_bo_unpin(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + } + } return 0; } diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index 8787ea89dc6..2bedce477a9 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -512,14 +512,16 @@ void r600_blit_fini(struct radeon_device *rdev) { int r; + if (rdev->r600_blit.shader_obj == NULL) + return; + /* If we can't reserve the bo, unref should be enough to destroy + * it when it becomes idle. + */ r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); - if (unlikely(r != 0)) { - dev_err(rdev->dev, "(%d) can't finish r600 blit\n", r); - goto out_unref; + if (!r) { + radeon_bo_unpin(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); } - radeon_bo_unpin(rdev->r600_blit.shader_obj); - radeon_bo_unreserve(rdev->r600_blit.shader_obj); -out_unref: radeon_bo_unref(&rdev->r600_blit.shader_obj); } diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 16f7317fa1a..7f17ddf1f45 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -975,10 +975,12 @@ int rv770_suspend(struct radeon_device *rdev) r600_wb_disable(rdev); rv770_pcie_gart_disable(rdev); /* unpin shaders bo */ - r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); - if (likely(r == 0)) { - radeon_bo_unpin(rdev->r600_blit.shader_obj); - radeon_bo_unreserve(rdev->r600_blit.shader_obj); + if (rdev->r600_blit.shader_obj) { + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (likely(r == 0)) { + radeon_bo_unpin(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + } } return 0; } -- cgit v1.2.3-70-g09d2 From 0a3f316370da07fcdb11fde4f5a683d60713b7fd Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 13 Jan 2010 15:16:39 +0100 Subject: drm/radeon/kms: Disable AGP is aperture size < 32M radeon KMS need a GART of at least 32M to properly work. This patch check the AGP aperture size and disable if it's less than 32M. Note than unlike non KMS path we don't staticaly allocate AGP memory so we are not wasting memory not used by graphic processing. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_agp.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index 220f454ea9f..c9ad7f5cc1a 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -133,6 +133,13 @@ int radeon_agp_init(struct radeon_device *rdev) bool is_v3; int ret; + if (rdev->ddev->agp->agp_info.aper_size < 32) { + dev_warn(rdev->dev, "AGP aperture to small (%dM) " + "need at least 32M, disabling AGP\n", + rdev->ddev->agp->agp_info.aper_size); + return -EINVAL; + } + /* Acquire AGP. */ if (!rdev->ddev->agp->acquired) { ret = drm_agp_acquire(rdev->ddev); -- cgit v1.2.3-70-g09d2 From 700a0cc088a42a2ed92c6f961534fdb38588af87 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 13 Jan 2010 15:16:38 +0100 Subject: drm/radeon/kms: Use radeon_agp_disable when disabling AGP Use same common function to disable agp so we replace the GART callback by the proper one when we do so. This fix oops if radeon_agp_init report failure. This patch also move radeon_agp_init out of *_mc_init for r600 & rv770 so that we can have a similar behavior than for previous hw, ie if agp_init fails it will fallback to GPU GART and disable AGP. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 4 +--- drivers/gpu/drm/radeon/r420.c | 4 +--- drivers/gpu/drm/radeon/r600.c | 9 +++++---- drivers/gpu/drm/radeon/radeon.h | 2 ++ drivers/gpu/drm/radeon/radeon_device.c | 1 + drivers/gpu/drm/radeon/rv770.c | 9 +++++---- 6 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 8760d66e058..62b27bede65 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -3399,9 +3399,7 @@ int r100_mc_init(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_AGP) { r = radeon_agp_init(rdev); if (r) { - printk(KERN_WARNING "[drm] Disabling AGP\n"); - rdev->flags &= ~RADEON_IS_AGP; - rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; + radeon_agp_disable(rdev); } else { rdev->mc.gtt_location = rdev->mc.agp_base; } diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 053404e71a9..4526faaacca 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -50,9 +50,7 @@ int r420_mc_init(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_AGP) { r = radeon_agp_init(rdev); if (r) { - printk(KERN_WARNING "[drm] Disabling AGP\n"); - rdev->flags &= ~RADEON_IS_AGP; - rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; + radeon_agp_disable(rdev); } else { rdev->mc.gtt_location = rdev->mc.agp_base; } diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 3e02dd403d7..b3713f61964 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -624,7 +624,6 @@ int r600_mc_init(struct radeon_device *rdev) fixed20_12 a; u32 tmp; int chansize, numchan; - int r; /* Get VRAM informations */ rdev->mc.vram_is_ddr = true; @@ -667,9 +666,6 @@ int r600_mc_init(struct radeon_device *rdev) rdev->mc.real_vram_size = rdev->mc.aper_size; if (rdev->flags & RADEON_IS_AGP) { - r = radeon_agp_init(rdev); - if (r) - return r; /* gtt_size is setup by radeon_agp_init */ rdev->mc.gtt_location = rdev->mc.agp_base; tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size; @@ -2028,6 +2024,11 @@ int r600_init(struct radeon_device *rdev) r = radeon_fence_driver_init(rdev); if (r) return r; + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) + radeon_agp_disable(rdev); + } r = r600_mc_init(rdev); if (r) return r; diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index eb5f99b9469..ab37dd0f2e7 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1017,6 +1017,8 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd)) /* Common functions */ +/* AGP */ +extern void radeon_agp_disable(struct radeon_device *rdev); extern int radeon_gart_table_vram_pin(struct radeon_device *rdev); extern int radeon_modeset_init(struct radeon_device *rdev); extern void radeon_modeset_fini(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 0c51f8e4661..768b1509fa0 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -544,6 +544,7 @@ void radeon_agp_disable(struct radeon_device *rdev) rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; rdev->asic->gart_set_page = &r100_pci_gart_set_page; } + rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; } void radeon_check_arguments(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 7f17ddf1f45..eb065bbe1ee 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -779,7 +779,6 @@ int rv770_mc_init(struct radeon_device *rdev) fixed20_12 a; u32 tmp; int chansize, numchan; - int r; /* Get VRAM informations */ rdev->mc.vram_is_ddr = true; @@ -822,9 +821,6 @@ int rv770_mc_init(struct radeon_device *rdev) rdev->mc.real_vram_size = rdev->mc.aper_size; if (rdev->flags & RADEON_IS_AGP) { - r = radeon_agp_init(rdev); - if (r) - return r; /* gtt_size is setup by radeon_agp_init */ rdev->mc.gtt_location = rdev->mc.agp_base; tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size; @@ -1039,6 +1035,11 @@ int rv770_init(struct radeon_device *rdev) r = radeon_fence_driver_init(rdev); if (r) return r; + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) + radeon_agp_disable(rdev); + } r = rv770_mc_init(rdev); if (r) return r; -- cgit v1.2.3-70-g09d2 From df1c93bae2b671e2aa50899a120af20afdbd504b Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 13 Jan 2010 22:28:36 +0100 Subject: drm/vmwgfx: Don't promote updates from GMR-backed scanouts to fullscreen. That's unnecessary since partial screen updates from GMRs are fast. Also fix cliprect pointer dereferencing Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index b1af76e371c..686692de209 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -553,9 +553,7 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, } *cmd; int i, increment = 1; - if (!num_clips || - !(dev_priv->fifo.capabilities & - SVGA_FIFO_CAP_SCREEN_OBJECT)) { + if (!num_clips) { num_clips = 1; clips = &norect; norect.x1 = norect.y1 = 0; @@ -574,10 +572,10 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, for (i = 0; i < num_clips; i++, clips += increment) { cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE); - cmd[i].body.x = cpu_to_le32(clips[i].x1); - cmd[i].body.y = cpu_to_le32(clips[i].y1); - cmd[i].body.width = cpu_to_le32(clips[i].x2 - clips[i].x1); - cmd[i].body.height = cpu_to_le32(clips[i].y2 - clips[i].y1); + cmd[i].body.x = cpu_to_le32(clips->x1); + cmd[i].body.y = cpu_to_le32(clips->y1); + cmd[i].body.width = cpu_to_le32(clips->x2 - clips->x1); + cmd[i].body.height = cpu_to_le32(clips->y2 - clips->y1); } vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips); -- cgit v1.2.3-70-g09d2 From 50ec3b7c35fda131e92abc6f9d93a230b7e009eb Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 13 Jan 2010 22:28:37 +0100 Subject: drm/vmwgfx: Fix an error path causing an oops. An error happening before the snooper.image member had been set up would cause a kfree of an arbitrary pointer. Set up the snooper.image member early. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 39 +++++++++++++++++--------------- 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index c012d5927f6..125c2f44f98 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -599,6 +599,27 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, if (unlikely(ret != 0)) goto out_err1; + + if (srf->flags & (1 << 9) && + srf->num_sizes == 1 && + srf->sizes[0].width == 64 && + srf->sizes[0].height == 64 && + srf->format == SVGA3D_A8R8G8B8) { + + srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL); + /* clear the image */ + if (srf->snooper.image) { + memset(srf->snooper.image, 0x00, 64 * 64 * 4); + } else { + DRM_ERROR("Failed to allocate cursor_image\n"); + ret = -ENOMEM; + goto out_err1; + } + } else { + srf->snooper.image = NULL; + } + srf->snooper.crtc = NULL; + user_srf->base.shareable = false; user_srf->base.tfile = NULL; @@ -622,24 +643,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, return ret; } - if (srf->flags & (1 << 9) && - srf->num_sizes == 1 && - srf->sizes[0].width == 64 && - srf->sizes[0].height == 64 && - srf->format == SVGA3D_A8R8G8B8) { - - srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL); - /* clear the image */ - if (srf->snooper.image) - memset(srf->snooper.image, 0x00, 64 * 64 * 4); - else - DRM_ERROR("Failed to allocate cursor_image\n"); - - } else { - srf->snooper.image = NULL; - } - srf->snooper.crtc = NULL; - rep->sid = user_srf->base.hash.key; if (rep->sid == SVGA3D_INVALID_ID) DRM_ERROR("Created bad Surface ID.\n"); -- cgit v1.2.3-70-g09d2 From 7704befbd599e9c9524f640e14658ca8ed9d8717 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 13 Jan 2010 22:28:38 +0100 Subject: drm/vmwgfx: Make fence sequences continous across a VT switch. A vt switch in stealth mode would take down the FIFO, and re- initialize fence sequence numbers. This patch saves the current state of the fence sequence when the FIFO is disabled. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 1db1ef30be2..70e4f5f0c12 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -217,6 +217,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->dev = dev; dev_priv->vmw_chipset = chipset; + dev_priv->last_read_sequence = (uint32_t) -100; mutex_init(&dev_priv->hw_mutex); mutex_init(&dev_priv->cmdbuf_mutex); rwlock_init(&dev_priv->resource_lock); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 01feb48af33..f7d5f70b52d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -98,8 +98,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) (unsigned int) min, (unsigned int) fifo->capabilities); - dev_priv->fence_seq = (uint32_t) -100; - dev_priv->last_read_sequence = (uint32_t) -100; + dev_priv->fence_seq = dev_priv->last_read_sequence; iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE); return vmw_fifo_send_fence(dev_priv, &dummy); -- cgit v1.2.3-70-g09d2 From effe1105bef07f42366c20eac41b80ff9fcf675e Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 13 Jan 2010 22:28:39 +0100 Subject: drm/vmwgfx: Use bo_driver::move_notify to unbind GMRs. This was previously done explicitly for overlay- and fb buffers. Now it's done for any buffer leaving the SYSTEM memory region. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 10 +++++++++- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 8 -------- drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c | 9 --------- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 23 ++++++++++++----------- 5 files changed, 22 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index d6f2d2b882e..4be47d84077 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -172,6 +172,13 @@ static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp) return 0; } +static void vmw_move_notify(struct ttm_buffer_object *bo, + struct ttm_mem_reg *new_mem) +{ + if (new_mem->mem_type != TTM_PL_SYSTEM) + vmw_dmabuf_gmr_unbind(bo); +} + /** * FIXME: We're using the old vmware polling method to sync. * Do this with fences instead. @@ -225,5 +232,6 @@ struct ttm_bo_driver vmw_bo_driver = { .sync_obj_wait = vmw_sync_obj_wait, .sync_obj_flush = vmw_sync_obj_flush, .sync_obj_unref = vmw_sync_obj_unref, - .sync_obj_ref = vmw_sync_obj_ref + .sync_obj_ref = vmw_sync_obj_ref, + .move_notify = vmw_move_notify }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index e61bd85b697..4c9d6b2b995 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -353,6 +353,7 @@ extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, struct vmw_dma_buffer *bo); extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv, struct vmw_dma_buffer *bo); +extern void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo); extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 641dde76ada..4f4f6432be8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -649,14 +649,6 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, if (unlikely(ret != 0)) goto err_unlock; - if (vmw_bo->gmr_bound) { - vmw_gmr_unbind(vmw_priv, vmw_bo->gmr_id); - spin_lock(&bo->glob->lru_lock); - ida_remove(&vmw_priv->gmr_ida, vmw_bo->gmr_id); - spin_unlock(&bo->glob->lru_lock); - vmw_bo->gmr_bound = NULL; - } - ret = ttm_bo_validate(bo, &ne_placement, false, false); ttm_bo_unreserve(bo); err_unlock: diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c index bb6e6a096d2..5b6eabeb7f5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c @@ -104,7 +104,6 @@ static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv, bool pin, bool interruptible) { struct ttm_buffer_object *bo = &buf->base; - struct ttm_bo_global *glob = bo->glob; struct ttm_placement *overlay_placement = &vmw_vram_placement; int ret; @@ -116,14 +115,6 @@ static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv, if (unlikely(ret != 0)) goto err; - if (buf->gmr_bound) { - vmw_gmr_unbind(dev_priv, buf->gmr_id); - spin_lock(&glob->lru_lock); - ida_remove(&dev_priv->gmr_ida, buf->gmr_id); - spin_unlock(&glob->lru_lock); - buf->gmr_bound = NULL; - } - if (pin) overlay_placement = &vmw_vram_ne_placement; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 125c2f44f98..e0878077e8a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -757,20 +757,29 @@ static size_t vmw_dmabuf_acc_size(struct ttm_bo_global *glob, return bo_user_size + page_array_size; } -void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) +void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo) { struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); struct ttm_bo_global *glob = bo->glob; struct vmw_private *dev_priv = container_of(bo->bdev, struct vmw_private, bdev); - ttm_mem_global_free(glob->mem_glob, bo->acc_size); if (vmw_bo->gmr_bound) { vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id); spin_lock(&glob->lru_lock); ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id); spin_unlock(&glob->lru_lock); + vmw_bo->gmr_bound = false; } +} + +void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) +{ + struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); + struct ttm_bo_global *glob = bo->glob; + + vmw_dmabuf_gmr_unbind(bo); + ttm_mem_global_free(glob->mem_glob, bo->acc_size); kfree(vmw_bo); } @@ -816,18 +825,10 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv, static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) { struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo); - struct vmw_dma_buffer *vmw_bo = &vmw_user_bo->dma; struct ttm_bo_global *glob = bo->glob; - struct vmw_private *dev_priv = - container_of(bo->bdev, struct vmw_private, bdev); + vmw_dmabuf_gmr_unbind(bo); ttm_mem_global_free(glob->mem_glob, bo->acc_size); - if (vmw_bo->gmr_bound) { - vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id); - spin_lock(&glob->lru_lock); - ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id); - spin_unlock(&glob->lru_lock); - } kfree(vmw_user_bo); } -- cgit v1.2.3-70-g09d2 From 3f09ea4ecdcbcea05541f83e557d6ce2e56626d8 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 13 Jan 2010 22:28:40 +0100 Subject: drm/ttm: Add a swap_notify callback. This is needed for a bugfix in the vmwgfx driver. Drivers may have GPU bindings on buffers that core TTM is not aware of, and TTM may view those buffers as ordinary system memory buffers. Add a notifier to such drivers when TTM is about to move the buffer contents out to swappable memory. The driver must then release any private GPU bindings on those buffers. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 3 +++ include/drm/ttm/ttm_bo_driver.h | 5 +++++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 2920f9a279e..e10a04e7c4e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1844,6 +1844,9 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink) * anyone tries to access a ttm page. */ + if (bo->bdev->driver->swap_notify) + bo->bdev->driver->swap_notify(bo); + ret = ttm_tt_swapout(bo->ttm, bo->persistant_swap_storage); out: diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index ff7664e0c3c..4c4e0f8375b 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -353,6 +353,11 @@ struct ttm_bo_driver { /* notify the driver we are taking a fault on this BO * and have reserved it */ void (*fault_reserve_notify)(struct ttm_buffer_object *bo); + + /** + * notify the driver that we're about to swap out this bo + */ + void (*swap_notify) (struct ttm_buffer_object *bo); }; /** -- cgit v1.2.3-70-g09d2 From 476d51dbdbaa2e61fa4899459c658f476eee3fd9 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 13 Jan 2010 22:28:41 +0100 Subject: drm/vmwgfx: Implement a swap_notify callback. Unbind GMR bindings on the buffer about to be swapped out. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index 4be47d84077..37a81925b15 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -179,6 +179,11 @@ static void vmw_move_notify(struct ttm_buffer_object *bo, vmw_dmabuf_gmr_unbind(bo); } +static void vmw_swap_notify(struct ttm_buffer_object *bo) +{ + vmw_dmabuf_gmr_unbind(bo); +} + /** * FIXME: We're using the old vmware polling method to sync. * Do this with fences instead. @@ -233,5 +238,6 @@ struct ttm_bo_driver vmw_bo_driver = { .sync_obj_flush = vmw_sync_obj_flush, .sync_obj_unref = vmw_sync_obj_unref, .sync_obj_ref = vmw_sync_obj_ref, - .move_notify = vmw_move_notify + .move_notify = vmw_move_notify, + .swap_notify = vmw_swap_notify }; -- cgit v1.2.3-70-g09d2 From e99e1e7893ac80fe769477cb1ddd4b482cef8902 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 13 Jan 2010 22:28:42 +0100 Subject: drm/ttm: Export symbols needed for vmwgfx suspend / resume operations. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 1 + drivers/gpu/drm/ttm/ttm_lock.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index e10a04e7c4e..7a64f07b120 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1867,3 +1867,4 @@ void ttm_bo_swapout_all(struct ttm_bo_device *bdev) while (ttm_bo_swapout(&bdev->glob->shrink) == 0) ; } +EXPORT_SYMBOL(ttm_bo_swapout_all); diff --git a/drivers/gpu/drm/ttm/ttm_lock.c b/drivers/gpu/drm/ttm/ttm_lock.c index f619ebcaa4e..3d172ef04ee 100644 --- a/drivers/gpu/drm/ttm/ttm_lock.c +++ b/drivers/gpu/drm/ttm/ttm_lock.c @@ -288,6 +288,7 @@ void ttm_suspend_unlock(struct ttm_lock *lock) wake_up_all(&lock->queue); spin_unlock(&lock->lock); } +EXPORT_SYMBOL(ttm_suspend_unlock); static bool __ttm_suspend_lock(struct ttm_lock *lock) { @@ -309,3 +310,4 @@ void ttm_suspend_lock(struct ttm_lock *lock) { wait_event(lock->queue, __ttm_suspend_lock(lock)); } +EXPORT_SYMBOL(ttm_suspend_lock); -- cgit v1.2.3-70-g09d2 From d9f36a0051b7c0382107cb0342af1126a6eb627d Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 13 Jan 2010 22:28:43 +0100 Subject: drm/vmwgfx: Implement basic pm operations. Currently we really only support S3, since the device doesn't support saving of the 3D state. On S3/S4, move all buffer objects to swappable memory and take down GMR bindings. We need to do that from a PM notifier since we can't do persistant memory allocations from the standard PM callbacks. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 62 ++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 ++ 2 files changed, 63 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 70e4f5f0c12..dedd121d8fe 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -147,6 +147,8 @@ static char *vmw_devname = "vmwgfx"; static int vmw_probe(struct pci_dev *, const struct pci_device_id *); static void vmw_master_init(struct vmw_master *); +static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, + void *ptr); static void vmw_print_capabilities(uint32_t capabilities) { @@ -352,6 +354,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) vmw_fb_init(dev_priv); } + dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier; + register_pm_notifier(&dev_priv->pm_nb); + return 0; out_no_device: @@ -386,6 +391,8 @@ static int vmw_driver_unload(struct drm_device *dev) DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n"); + unregister_pm_notifier(&dev_priv->pm_nb); + if (!dev_priv->stealth) { vmw_fb_close(dev_priv); vmw_kms_close(dev_priv); @@ -651,6 +658,57 @@ static void vmw_remove(struct pci_dev *pdev) drm_put_dev(dev); } +static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, + void *ptr) +{ + struct vmw_private *dev_priv = + container_of(nb, struct vmw_private, pm_nb); + struct vmw_master *vmaster = dev_priv->active_master; + + switch (val) { + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: + ttm_suspend_lock(&vmaster->lock); + + /** + * This empties VRAM and unbinds all GMR bindings. + * Buffer contents is moved to swappable memory. + */ + ttm_bo_swapout_all(&dev_priv->bdev); + break; + case PM_POST_HIBERNATION: + case PM_POST_SUSPEND: + ttm_suspend_unlock(&vmaster->lock); + break; + case PM_RESTORE_PREPARE: + break; + case PM_POST_RESTORE: + break; + default: + break; + } + return 0; +} + +/** + * These might not be needed with the virtual SVGA device. + */ + +int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + return 0; +} + +int vmw_pci_resume(struct pci_dev *pdev) +{ + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + return pci_enable_device(pdev); +} + static struct drm_driver driver = { .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_MODESET, @@ -690,7 +748,9 @@ static struct drm_driver driver = { .name = VMWGFX_DRIVER_NAME, .id_table = vmw_pci_id_list, .probe = vmw_probe, - .remove = vmw_remove + .remove = vmw_remove, + .suspend = vmw_pci_suspend, + .resume = vmw_pci_resume }, .name = VMWGFX_DRIVER_NAME, .desc = VMWGFX_DRIVER_DESC, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 4c9d6b2b995..7532b9b47ee 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -32,6 +32,7 @@ #include "drmP.h" #include "vmwgfx_drm.h" #include "drm_hashtab.h" +#include "linux/suspend.h" #include "ttm/ttm_bo_driver.h" #include "ttm/ttm_object.h" #include "ttm/ttm_lock.h" @@ -258,6 +259,7 @@ struct vmw_private { struct vmw_master *active_master; struct vmw_master fbdev_master; + struct notifier_block pm_nb; }; static inline struct vmw_private *vmw_priv(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From 354fb52cb6138de0e6cf84a0f6a7f3467586e390 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 13 Jan 2010 22:28:45 +0100 Subject: drm/ttm: Make sure system buffer objects has offset == 0. This is a convention that the vmwgfx driver has come to rely on. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 7a64f07b120..da3702135ad 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -426,7 +426,8 @@ moved: bdev->man[bo->mem.mem_type].gpu_offset; bo->cur_placement = bo->mem.placement; spin_unlock(&bo->lock); - } + } else + bo->offset = 0; return 0; -- cgit v1.2.3-70-g09d2 From 0a90dc51aa3162abb7cd64323ba2e6674e1c5ff4 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Mon, 11 Jan 2010 21:18:53 +0100 Subject: drm/nv50: wait for pgraph to idle before unloading the context This should fix the problem with gpu hangs people have had when closing channels. Signed-off-by: Maarten Maathuis Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_graph.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index ca79f32be44..56a9753db23 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -282,6 +282,7 @@ nv50_graph_unload_context(struct drm_device *dev) return 0; inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE; + nouveau_wait_for_idle(dev); nv_wr32(dev, 0x400500, fifo & ~1); nv_wr32(dev, 0x400784, inst); nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20); -- cgit v1.2.3-70-g09d2 From 9855e584d296a32bbcc1bb3d29b7e0ed078b03cc Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 12 Jan 2010 13:02:19 +1000 Subject: drm/nouveau: trust init table registers are safe Apparently the original reason for checking this was there were known register accesses that caused hangs on some chipsets. This was more than likely because of incorrect parsing of previous opcodes, and I hardly think aborting a script half way through is going to be any better (in fact, we have had bug reports where this has been the cause of s/r failures among other things). This patch (which has been in Fedora 12 for a long time now) removes all checking for known register ranges, and just leaves the check to ensure the access is within the mapped aperture to avoid an oops. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bios.c | 59 ++++++---------------------------- 1 file changed, 9 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index ba143972769..9710e69898f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -310,63 +310,22 @@ valid_reg(struct nvbios *bios, uint32_t reg) struct drm_device *dev = bios->dev; /* C51 has misaligned regs on purpose. Marvellous */ - if (reg & 0x2 || (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51)) { - NV_ERROR(dev, "========== misaligned reg 0x%08X ==========\n", - reg); - return 0; - } - /* - * Warn on C51 regs that have not been verified accessible in - * mmiotracing - */ + if (reg & 0x2 || + (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51)) + NV_ERROR(dev, "======= misaligned reg 0x%08X =======\n", reg); + + /* warn on C51 regs that haven't been verified accessible in tracing */ if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 && reg != 0x130d && reg != 0x1311 && reg != 0x60081d) NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n", reg); - /* Trust the init scripts on G80 */ - if (dev_priv->card_type >= NV_50) - return 1; - - #define WITHIN(x, y, z) ((x >= y) && (x < y + z)) - if (WITHIN(reg, NV_PMC_OFFSET, NV_PMC_SIZE)) - return 1; - if (WITHIN(reg, NV_PBUS_OFFSET, NV_PBUS_SIZE)) - return 1; - if (WITHIN(reg, NV_PFIFO_OFFSET, NV_PFIFO_SIZE)) - return 1; - if (dev_priv->VBIOS.pub.chip_version >= 0x30 && - (WITHIN(reg, 0x4000, 0x600) || reg == 0x00004600)) - return 1; - if (dev_priv->VBIOS.pub.chip_version >= 0x40 && - WITHIN(reg, 0xc000, 0x48)) - return 1; - if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0000d204) - return 1; - if (dev_priv->VBIOS.pub.chip_version >= 0x40) { - if (reg == 0x00011014 || reg == 0x00020328) - return 1; - if (WITHIN(reg, 0x88000, NV_PBUS_SIZE)) /* new PBUS */ - return 1; + if (reg >= (8*1024*1024)) { + NV_ERROR(dev, "=== reg 0x%08x out of mapped bounds ===\n", reg); + return 0; } - if (WITHIN(reg, NV_PFB_OFFSET, NV_PFB_SIZE)) - return 1; - if (WITHIN(reg, NV_PEXTDEV_OFFSET, NV_PEXTDEV_SIZE)) - return 1; - if (WITHIN(reg, NV_PCRTC0_OFFSET, NV_PCRTC0_SIZE * 2)) - return 1; - if (WITHIN(reg, NV_PRAMDAC0_OFFSET, NV_PRAMDAC0_SIZE * 2)) - return 1; - if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0070fff0) - return 1; - if (dev_priv->VBIOS.pub.chip_version == 0x51 && - WITHIN(reg, NV_PRAMIN_OFFSET, NV_PRAMIN_SIZE)) - return 1; - #undef WITHIN - NV_ERROR(dev, "========== unknown reg 0x%08X ==========\n", reg); - - return 0; + return 1; } static bool -- cgit v1.2.3-70-g09d2 From e147eae80afe98b86a7921a40a709584e6603e34 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 12 Jan 2010 15:28:19 +1000 Subject: drm/nouveau: wait on fence after bo move if validating for another channel Not an ideal solution, but it'll do for the moment for correctness. We need to come up with a nicer way to manage inter-channel sync, the hw is unfortunately a little lacking in this area. Should fix some resume corruption, as well as corruption that may be seen while under memory pressure. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e342a418d43..db0ed4c13f9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -469,6 +469,8 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, evict, no_wait, new_mem); + if (nvbo->channel && nvbo->channel != chan) + ret = nouveau_fence_wait(fence, NULL, false, false); nouveau_fence_unref((void *)&fence); return ret; } -- cgit v1.2.3-70-g09d2 From 77cb5c75e89ccfeb993d9dec37f8edb3a855e9f4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 13 Jan 2010 11:22:33 +1000 Subject: drm/nouveau: remove PRIV0 check in nouveau_mem_close() We don't setup PRIV0 anymore, so this is unnecessary. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_mem.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index fb9bdd6edf1..be4c7781d76 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -383,10 +383,7 @@ void nouveau_mem_close(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->ttm.bdev.man[TTM_PL_PRIV0].has_type) - ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_PRIV0); ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); - ttm_bo_device_release(&dev_priv->ttm.bdev); nouveau_ttm_global_release(dev_priv); -- cgit v1.2.3-70-g09d2 From ed42f8240cfea13580fe91195e52c5247275e7df Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 14 Jan 2010 15:58:10 +1000 Subject: drm/nouveau: assume no nv04 board has a DCB table There's a report of a TNT2 where the DCB table pointer is *not* NULL (it contains a part of a VBIOS data string), and we assume this means a DCB table is present, causing all kinds of hilarity. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bios.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 9710e69898f..9dd2efa07f6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -5523,11 +5523,13 @@ void merge_like_dcb_entries(struct drm_device *dev, struct parsed_dcb *dcb) dcb->entries = newentries; } -static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) +static int +parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) { + struct drm_nouveau_private *dev_priv = dev->dev_private; struct bios_parsed_dcb *bdcb = &bios->bdcb; struct parsed_dcb *dcb; - uint16_t dcbptr, i2ctabptr = 0; + uint16_t dcbptr = 0, i2ctabptr = 0; uint8_t *dcbtable; uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES; bool configblock = true; @@ -5538,16 +5540,18 @@ static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool two dcb->entries = 0; /* get the offset from 0x36 */ - dcbptr = ROM16(bios->data[0x36]); + if (dev_priv->card_type > NV_04) { + dcbptr = ROM16(bios->data[0x36]); + if (dcbptr == 0x0000) + NV_WARN(dev, "No output data (DCB) found in BIOS\n"); + } + /* this situation likely means a really old card, pre DCB */ if (dcbptr == 0x0) { - NV_WARN(dev, "No output data (DCB) found in BIOS, " - "assuming a CRT output exists\n"); - /* this situation likely means a really old card, pre DCB */ + NV_INFO(dev, "Assuming a CRT output exists\n"); fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1); - if (nv04_tv_identify(dev, - bios->legacy.i2c_indices.tv) >= 0) + if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) fabricate_tv_output(dcb, twoHeads); return 0; -- cgit v1.2.3-70-g09d2 From b0d2de860bd621959bc826ffd42618fe1de37a61 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 14 Jan 2010 17:53:04 +1000 Subject: drm/nouveau: less magic DCB 1.5 parsing This in the very least matches the parsing of all the previously known entries, and hopefully (at least closer to) correct for any we haven't seen yet. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bios.c | 79 +++++++++++++++++----------------- 1 file changed, 40 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 9dd2efa07f6..ca2fcdf32b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -5393,52 +5393,49 @@ static bool parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb, uint32_t conn, uint32_t conf, struct dcb_entry *entry) { - if (conn != 0xf0003f00 && conn != 0xf2247f10 && conn != 0xf2204001 && - conn != 0xf2204301 && conn != 0xf2204311 && conn != 0xf2208001 && - conn != 0xf2244001 && conn != 0xf2244301 && conn != 0xf2244311 && - conn != 0xf4204011 && conn != 0xf4208011 && conn != 0xf4248011 && - conn != 0xf2045ff2 && conn != 0xf2045f14 && conn != 0xf207df14 && - conn != 0xf2205004 && conn != 0xf2209004) { - NV_ERROR(dev, "Unknown DCB 1.5 entry, please report\n"); - - /* cause output setting to fail for !TV, so message is seen */ - if ((conn & 0xf) != 0x1) - dcb->entries = 0; - - return false; - } - /* most of the below is a "best guess" atm */ - entry->type = conn & 0xf; - if (entry->type == 2) - /* another way of specifying straps based lvds... */ + switch (conn & 0x0000000f) { + case 0: + entry->type = OUTPUT_ANALOG; + break; + case 1: + entry->type = OUTPUT_TV; + break; + case 2: + case 3: entry->type = OUTPUT_LVDS; - if (entry->type == 4) { /* digital */ - if (conn & 0x10) - entry->type = OUTPUT_LVDS; - else + break; + case 4: + switch ((conn & 0x000000f0) >> 4) { + case 0: entry->type = OUTPUT_TMDS; + break; + case 1: + entry->type = OUTPUT_LVDS; + break; + default: + NV_ERROR(dev, "Unknown DCB subtype 4/%d\n", + (conn & 0x000000f0) >> 4); + return false; + } + break; + default: + NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f); + return false; } - /* what's in bits 5-13? could be some encoder maker thing, in tv case */ - entry->i2c_index = (conn >> 14) & 0xf; - /* raw heads field is in range 0-1, so move to 1-2 */ - entry->heads = ((conn >> 18) & 0x7) + 1; - entry->location = (conn >> 21) & 0xf; - /* unused: entry->bus = (conn >> 25) & 0x7; */ - /* set or to be same as heads -- hopefully safe enough */ - entry->or = entry->heads; + + entry->i2c_index = (conn & 0x0003c000) >> 14; + entry->heads = ((conn & 0x001c0000) >> 18) + 1; + entry->or = entry->heads; /* same as heads, hopefully safe enough */ + entry->location = (conn & 0x01e00000) >> 21; + entry->bus = (conn & 0x0e000000) >> 25; entry->duallink_possible = false; switch (entry->type) { case OUTPUT_ANALOG: entry->crtconf.maxfreq = (conf & 0xffff) * 10; break; - case OUTPUT_LVDS: - /* - * This is probably buried in conn's unknown bits. - * This will upset EDID-ful models, if they exist - */ - entry->lvdsconf.use_straps_for_mode = true; - entry->lvdsconf.use_power_scripts = true; + case OUTPUT_TV: + entry->tvconf.has_component_output = false; break; case OUTPUT_TMDS: /* @@ -5447,8 +5444,12 @@ parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb, */ fabricate_vga_output(dcb, entry->i2c_index, entry->heads); break; - case OUTPUT_TV: - entry->tvconf.has_component_output = false; + case OUTPUT_LVDS: + if ((conn & 0x00003f00) != 0x10) + entry->lvdsconf.use_straps_for_mode = true; + entry->lvdsconf.use_power_scripts = true; + break; + default: break; } -- cgit v1.2.3-70-g09d2 From 716abaa8e52548e8863831cb32984655f46b5566 Mon Sep 17 00:00:00 2001 From: Marcin Kościelnicki Date: Tue, 12 Jan 2010 18:21:56 +0000 Subject: drm/nv50: Fix typo in PGRAPH initialisation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables streamout functionality. Signed-off-by: Marcin Kościelnicki Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_graph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 56a9753db23..20319e59d36 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -84,7 +84,7 @@ nv50_graph_init_regs__nv(struct drm_device *dev) nv_wr32(dev, 0x400804, 0xc0000000); nv_wr32(dev, 0x406800, 0xc0000000); nv_wr32(dev, 0x400c04, 0xc0000000); - nv_wr32(dev, 0x401804, 0xc0000000); + nv_wr32(dev, 0x401800, 0xc0000000); nv_wr32(dev, 0x405018, 0xc0000000); nv_wr32(dev, 0x402000, 0xc0000000); -- cgit v1.2.3-70-g09d2 From a0e803a2112398150daa4d88c9d58409e0cf0b6c Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 13 Jan 2010 12:09:08 +0100 Subject: iwmc3200wifi: Add UMAC wifi headers to the pmkid command Without this header, we can trigger a UMAC crash with debug enabled UMACs. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/commands.c | 4 ++++ drivers/net/wireless/iwmc3200wifi/commands.h | 1 + 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 777584d76a8..1e41ad0fcad 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -973,6 +973,10 @@ int iwm_send_pmkid_update(struct iwm_priv *iwm, memset(&update, 0, sizeof(struct iwm_umac_pmkid_update)); + update.hdr.oid = UMAC_WIFI_IF_CMD_PMKID_UPDATE; + update.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_pmkid_update) - + sizeof(struct iwm_umac_wifi_if)); + update.command = cpu_to_le32(command); if (pmksa->bssid) memcpy(&update.bssid, pmksa->bssid, ETH_ALEN); diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h index 06af0552cd7..3dfd9f0e900 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.h +++ b/drivers/net/wireless/iwmc3200wifi/commands.h @@ -463,6 +463,7 @@ struct iwm_umac_cmd_stop_resume_tx { #define IWM_CMD_PMKID_FLUSH 3 struct iwm_umac_pmkid_update { + struct iwm_umac_wifi_if hdr; __le32 command; u8 bssid[ETH_ALEN]; __le16 reserved; -- cgit v1.2.3-70-g09d2 From b79d8a65d52d3d80204e1bad30ee57bb5a58ced1 Mon Sep 17 00:00:00 2001 From: Andrea Tacconi Date: Thu, 14 Jan 2010 14:52:37 +0100 Subject: drm/nouveau: add NV18 device id to call_lvds_manufacturer_script This fixes imac black screen (NV18 card) Signed-off-by: Andrea Tacconi Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index ca2fcdf32b8..03f1ddbaa2d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -3155,7 +3155,7 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr } #ifdef __powerpc__ /* Powerbook specific quirks */ - if (script == LVDS_RESET && ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0329)) + if (script == LVDS_RESET && ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0189 || (dev->pci_device & 0xffff) == 0x0329)) nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72); if ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0189 || (dev->pci_device & 0xffff) == 0x0329) { if (script == LVDS_PANEL_ON) { -- cgit v1.2.3-70-g09d2 From 3d9aefb8bd1be2b5e07acf0f938c21769f03cc64 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 14 Jan 2010 14:56:54 +0100 Subject: drm/nouveau: Break some long lines. Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bios.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 03f1ddbaa2d..d7f8d8b4a4b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -3155,16 +3155,25 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr } #ifdef __powerpc__ /* Powerbook specific quirks */ - if (script == LVDS_RESET && ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0189 || (dev->pci_device & 0xffff) == 0x0329)) - nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72); - if ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0189 || (dev->pci_device & 0xffff) == 0x0329) { - if (script == LVDS_PANEL_ON) { - bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) | (1 << 31)); - bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1); - } - if (script == LVDS_PANEL_OFF) { - bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) & ~(1 << 31)); - bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3); + if ((dev->pci_device & 0xffff) == 0x0179 || + (dev->pci_device & 0xffff) == 0x0189 || + (dev->pci_device & 0xffff) == 0x0329) { + if (script == LVDS_RESET) { + nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72); + + } else if (script == LVDS_PANEL_ON) { + bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, + bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) + | (1 << 31)); + bios_wr32(bios, NV_PCRTC_GPIO_EXT, + bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1); + + } else if (script == LVDS_PANEL_OFF) { + bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, + bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) + & ~(1 << 31)); + bios_wr32(bios, NV_PCRTC_GPIO_EXT, + bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3); } } #endif -- cgit v1.2.3-70-g09d2 From c8ebe275790f2c5efc3ffec515c93b7a139829d3 Mon Sep 17 00:00:00 2001 From: Xavier Chantry Date: Mon, 11 Jan 2010 22:42:21 +0100 Subject: drm/nouveau: fix edid memleak in nouveau_connector This was spotted by kmemleak. Signed-off-by: Xavier Chantry Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_connector.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 5a10deb8bdb..54c85305a0f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -83,14 +83,16 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder) static void nouveau_connector_destroy(struct drm_connector *drm_connector) { - struct nouveau_connector *connector = nouveau_connector(drm_connector); - struct drm_device *dev = connector->base.dev; + struct nouveau_connector *nv_connector = + nouveau_connector(drm_connector); + struct drm_device *dev = nv_connector->base.dev; NV_DEBUG_KMS(dev, "\n"); - if (!connector) + if (!nv_connector) return; + kfree(nv_connector->edid); drm_sysfs_connector_remove(drm_connector); drm_connector_cleanup(drm_connector); kfree(drm_connector); @@ -237,6 +239,9 @@ nouveau_connector_detect(struct drm_connector *connector) return connector_status_connected; } + kfree(nv_connector->edid); + nv_connector->edid = NULL; + i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); if (i2c) { nouveau_connector_ddc_prepare(connector, &flags); @@ -687,8 +692,12 @@ nouveau_connector_create_lvds(struct drm_device *dev, */ if (!nv_connector->edid && !nv_connector->native_mode && !dev_priv->VBIOS.pub.fp_no_ddc) { - nv_connector->edid = + struct edid *edid = (struct edid *)nouveau_bios_embedded_edid(dev); + if (edid) { + nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + *(nv_connector->edid) = *edid; + } } if (!nv_connector->edid) -- cgit v1.2.3-70-g09d2 From 0ed3165e55fdedee6fc04b757907a2d5ccacdf18 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 14 Jan 2010 15:47:03 +0100 Subject: drm/nouveau: Fallback to analog load detection when the EDID block is invalid. Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_connector.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 54c85305a0f..3dc7e09da28 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -252,7 +252,7 @@ nouveau_connector_detect(struct drm_connector *connector) if (!nv_connector->edid) { NV_ERROR(dev, "DDC responded, but no EDID for %s\n", drm_get_connector_name(connector)); - return connector_status_disconnected; + goto detect_analog; } if (nv_encoder->dcb->type == OUTPUT_DP && @@ -286,6 +286,7 @@ nouveau_connector_detect(struct drm_connector *connector) return connector_status_connected; } +detect_analog: nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); if (!nv_encoder) nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); -- cgit v1.2.3-70-g09d2 From b8780e2ad20feb8d086bc961a678e8fdb4fa296b Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 14 Jan 2010 15:54:23 +0100 Subject: drm/nouveau: Unset the EDID connector property when the EDID block goes away. Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_connector.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 3dc7e09da28..8da35281a0c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -239,8 +239,12 @@ nouveau_connector_detect(struct drm_connector *connector) return connector_status_connected; } - kfree(nv_connector->edid); - nv_connector->edid = NULL; + /* Cleanup the previous EDID block. */ + if (nv_connector->edid) { + drm_mode_connector_update_edid_property(connector, NULL); + kfree(nv_connector->edid); + nv_connector->edid = NULL; + } i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); if (i2c) { -- cgit v1.2.3-70-g09d2 From ac8fb975e8c88d312a376b035494be17548d01c6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 15 Jan 2010 09:24:20 +1000 Subject: drm/nouveau: reserve VGA area for the moment This is to prevent things such as GART tables and other important GPU structures being allocated there before we take over fbcon ourselves. This is more of a workaround for the moment, a better solution will require some more invasive changes, but it'll be done at some point. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drv.h | 2 ++ drivers/gpu/drm/nouveau/nouveau_mem.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 026419fe879..cc36866e2a9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -509,6 +509,8 @@ struct drm_nouveau_private { void __iomem *ramin; uint32_t ramin_size; + struct nouveau_bo *vga_ram; + struct workqueue_struct *wq; struct work_struct irq_work; diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index be4c7781d76..186f34b01f2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -383,6 +383,9 @@ void nouveau_mem_close(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + nouveau_bo_unpin(dev_priv->vga_ram); + nouveau_bo_ref(NULL, &dev_priv->vga_ram); + ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); ttm_bo_device_release(&dev_priv->ttm.bdev); @@ -619,6 +622,15 @@ nouveau_mem_init(struct drm_device *dev) return ret; } + ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, + 0, 0, true, true, &dev_priv->vga_ram); + if (ret == 0) + ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM); + if (ret) { + NV_WARN(dev, "failed to reserve VGA memory\n"); + nouveau_bo_ref(NULL, &dev_priv->vga_ram); + } + /* GART */ #if !defined(__powerpc__) && !defined(__ia64__) if (drm_device_is_agp(dev) && dev->agp) { @@ -650,6 +662,7 @@ nouveau_mem_init(struct drm_device *dev) dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1), drm_get_resource_len(dev, 1), DRM_MTRR_WC); + return 0; } -- cgit v1.2.3-70-g09d2 From 75136d48e85915fd78a072f22897622b5d4c1814 Mon Sep 17 00:00:00 2001 From: Markus Pietrek Date: Fri, 15 Jan 2010 08:33:20 +0900 Subject: serial: sh-sci: using correct fifo size for SCIF and SCIFA ports. The sh-sci driver used the wrong fifosize for PORT_SCIFA and PORT_SCIF ports. If an incorrect size is used, the serial core will enforce an early shutdown on the port, especially with baudrates < 9600. Signed-off-by: Markus Pietrek Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 37f0de9dd9c..42f3333c4ad 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1052,7 +1052,18 @@ static void __devinit sci_init_single(struct platform_device *dev, sci_port->port.ops = &sci_uart_ops; sci_port->port.iotype = UPIO_MEM; sci_port->port.line = index; - sci_port->port.fifosize = 1; + + switch (p->type) { + case PORT_SCIFA: + sci_port->port.fifosize = 64; + break; + case PORT_SCIF: + sci_port->port.fifosize = 16; + break; + default: + sci_port->port.fifosize = 1; + break; + } if (dev) { sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL; -- cgit v1.2.3-70-g09d2 From 12f735b79f0ad63964dedabed3eee8a581bb66a5 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Sun, 10 Jan 2010 20:10:53 +0100 Subject: drm/nouveau: check pushbuffer bounds in ioctl Currently there is no check that the pushbuffer request bounds are inside the TTM BO. This allows to instruct the kernel to do relocations on user-selected addresses, since the relocation bounds checking relies on the request bounds. This can oops the kernel accidentally and is easily exploitable. This patch adds bound checking and alignment checking for ->offset and ->nr_dwords. It also makes some variables unsigned, which should have no effect, but prevents possible bounds checking problems. Signed-off-by: Luca Barbieri Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_gem.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 2009db2426c..50483304408 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -466,13 +466,14 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size) static int nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo, struct drm_nouveau_gem_pushbuf_bo *bo, - int nr_relocs, uint64_t ptr_relocs, - int nr_dwords, int first_dword, + unsigned nr_relocs, uint64_t ptr_relocs, + unsigned nr_dwords, unsigned first_dword, uint32_t *pushbuf, bool is_iomem) { struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; struct drm_device *dev = chan->dev; - int ret = 0, i; + int ret = 0; + unsigned i; reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc)); if (IS_ERR(reloc)) @@ -667,6 +668,18 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, } pbbo = nouveau_gem_object(gem); + if ((req->offset & 3) || req->nr_dwords < 2 || + (unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size || + (unsigned long)req->nr_dwords > + ((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) { + NV_ERROR(dev, "pb call misaligned or out of bounds: " + "%d + %d * 4 > %ld\n", + req->offset, req->nr_dwords, pbbo->bo.mem.size); + ret = -EINVAL; + drm_gem_object_unreference(gem); + goto out; + } + ret = ttm_bo_reserve(&pbbo->bo, false, false, true, chan->fence.sequence); if (ret) { -- cgit v1.2.3-70-g09d2 From 46759a7c132648d79121518d2f7c34edc3f0cf58 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sun, 10 Jan 2010 01:43:14 +0000 Subject: powerpc/macintosh: Make Open Firmware device id constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The match_table field of the struct of_device_id is constant in so it is worth to make the initialization data also constant. The semantic match that finds this kind of pattern is as follows: (http://coccinelle.lip6.fr/) // @r@ disable decl_init,const_decl_init; identifier I1, I2, x; @@ struct I1 { ... const struct I2 *x; ... }; @s@ identifier r.I1, y; identifier r.x, E; @@ struct I1 y = { .x = E, }; @c@ identifier r.I2; identifier s.E; @@ const struct I2 E[] = ... ; @depends on !c@ identifier r.I2; identifier s.E; @@ + const struct I2 E[] = ...; // Signed-off-by: Márton Németh Cc: Julia Lawall Cc: cocci@diku.dk Signed-off-by: Benjamin Herrenschmidt --- drivers/macintosh/smu.c | 2 +- drivers/macintosh/therm_pm72.c | 2 +- drivers/macintosh/therm_windtunnel.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 96faa799b82..f96feeb6b9c 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -660,7 +660,7 @@ static int smu_platform_probe(struct of_device* dev, return 0; } -static struct of_device_id smu_platform_match[] = +static const struct of_device_id smu_platform_match[] = { { .type = "smu", diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index ea32c7e5a9a..454bc501df3 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -2211,7 +2211,7 @@ static int fcu_of_remove(struct of_device* dev) return 0; } -static struct of_device_id fcu_match[] = +static const struct of_device_id fcu_match[] = { { .type = "fcu", diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 3fbe41b0ac0..ba48fd76396 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -457,7 +457,7 @@ therm_of_remove( struct of_device *dev ) return 0; } -static struct of_device_id therm_of_match[] = {{ +static const struct of_device_id therm_of_match[] = {{ .name = "fan", .compatible = "adm1030" }, {} -- cgit v1.2.3-70-g09d2 From 02ab851324dc7e2fc75787f7fae71187092be7ed Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 10 Jan 2010 17:51:42 +0000 Subject: serial/pmac_zilog: Workaround problem due to interrupt on closed port It seems that in qemu, we can see an interrupt in R3 despite the fact that it's masked in W1. The chip doesn't actually issue an interrupt, but we can "see" it when taking an interrupt for the other channel. This may be a qemu bug ... or not, so let's be safe and avoid calling into the UART layer when that happens which woulc cause a crash. Signed-off-by: Benjamin Herrenschmidt Acked-by: Rob Landley --- drivers/serial/pmac_zilog.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 0700cd10b97..683e66f18e8 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -411,6 +411,17 @@ static void pmz_transmit_chars(struct uart_pmac_port *uap) goto ack_tx_int; } + /* Under some circumstances, we see interrupts reported for + * a closed channel. The interrupt mask in R1 is clear, but + * R3 still signals the interrupts and we see them when taking + * an interrupt for the other channel (this could be a qemu + * bug but since the ESCC doc doesn't specify precsiely whether + * R3 interrup status bits are masked by R1 interrupt enable + * bits, better safe than sorry). --BenH. + */ + if (!ZS_IS_OPEN(uap)) + goto ack_tx_int; + if (uap->port.x_char) { uap->flags |= PMACZILOG_FLAG_TX_ACTIVE; write_zsdata(uap, uap->port.x_char); -- cgit v1.2.3-70-g09d2 From aa8b83cb0b48e3cac58a3b75ad9c556564c5fe9d Mon Sep 17 00:00:00 2001 From: Kamalesh Babulal Date: Fri, 25 Sep 2009 03:31:43 +0000 Subject: powerpc/hvc: Driver build breaks with !HVC_CONSOLE Hi Stephen, next-20090925 randconfig build breaks on hvcs driver on powerpc, with HVC_CONSOLE=n. ERROR: ".hvc_put_chars" [drivers/char/hvcs.ko] undefined! ERROR: ".hvc_get_chars" [drivers/char/hvcs.ko] undefined! adding the dependency of HVC_CONSOLE helped Signed-off-by: Kamalesh Babulal Signed-off-by: Benjamin Herrenschmidt --- drivers/char/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 31be3ac2e21..e023682be2c 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -669,7 +669,7 @@ config VIRTIO_CONSOLE config HVCS tristate "IBM Hypervisor Virtual Console Server support" - depends on PPC_PSERIES + depends on PPC_PSERIES && HVC_CONSOLE help Partitionable IBM Power5 ppc64 machines allow hosting of firmware virtual consoles from one Linux partition by -- cgit v1.2.3-70-g09d2 From 79b7dcb2af7da728819cf060b94ce8c9ead36f7e Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 14 Jan 2010 19:02:20 +0100 Subject: drm: EDID accept separate sync video mode X is accepting such video mode, do the same. Pointed out by Joshua Roys on IRC. Fix https://bugzilla.redhat.com/show_bug.cgi?id=540024 [fix printf to use composite not integrated :- airlied] Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index defcaf10846..f665b05592f 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -633,8 +633,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, return NULL; } if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) { - printk(KERN_WARNING "integrated sync not supported\n"); - return NULL; + printk(KERN_WARNING "composite sync not supported\n"); } /* it is incorrect if hsync/vsync width is zero */ -- cgit v1.2.3-70-g09d2 From 926311fd7dabcd284a1e8a87a3e2bb5f929c0c60 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 11 Jan 2010 20:58:21 +0100 Subject: amd64_edac: Ensure index stays within bounds in amd64_get_scrub_rate Add a missing iterator variable thus fixing the conditional of the for-loop in amd64_get_scrub_rate(). Signed-off-by: Roel Kluin Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index c5facd951dd..000dc67b85b 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -197,7 +197,7 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw) edac_printk(KERN_DEBUG, EDAC_MC, "pci-read, sdram scrub control value: %d \n", scrubval); - for (i = 0; ARRAY_SIZE(scrubrates); i++) { + for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { if (scrubrates[i].scrubval == scrubval) { *bw = scrubrates[i].bandwidth; status = 0; -- cgit v1.2.3-70-g09d2 From c7c85101afd0cb8ce497456d12ee1cad4aad152f Mon Sep 17 00:00:00 2001 From: Zou Nan hai Date: Fri, 15 Jan 2010 10:29:06 +0800 Subject: drm/i915: remove loop in Ironlake interrupt handler On Ironlake, there is an interrupt master control bit. With the bit disabled before clearing IIR, we do not need to handle extra interrupt in a loop. This patch removes the loop in Ironlake interrupt handler. It fixed irq lost issue on some Ironlake platforms. Cc: Stable Team Signed-off-by: Zou Nan hai Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_irq.c | 68 ++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7cd8110051b..89a071a3e6f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -274,7 +274,6 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = IRQ_NONE; u32 de_iir, gt_iir, de_ier, pch_iir; - u32 new_de_iir, new_gt_iir, new_pch_iir; struct drm_i915_master_private *master_priv; /* disable master interrupt before clearing iir */ @@ -286,51 +285,42 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) gt_iir = I915_READ(GTIIR); pch_iir = I915_READ(SDEIIR); - for (;;) { - if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) - break; - - ret = IRQ_HANDLED; + if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) + goto done; - /* should clear PCH hotplug event before clear CPU irq */ - I915_WRITE(SDEIIR, pch_iir); - new_pch_iir = I915_READ(SDEIIR); + ret = IRQ_HANDLED; - I915_WRITE(DEIIR, de_iir); - new_de_iir = I915_READ(DEIIR); - I915_WRITE(GTIIR, gt_iir); - new_gt_iir = I915_READ(GTIIR); - - if (dev->primary->master) { - master_priv = dev->primary->master->driver_priv; - if (master_priv->sarea_priv) - master_priv->sarea_priv->last_dispatch = - READ_BREADCRUMB(dev_priv); - } - - if (gt_iir & GT_USER_INTERRUPT) { - u32 seqno = i915_get_gem_seqno(dev); - dev_priv->mm.irq_gem_seqno = seqno; - trace_i915_gem_request_complete(dev, seqno); - DRM_WAKEUP(&dev_priv->irq_queue); - dev_priv->hangcheck_count = 0; - mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); - } + if (dev->primary->master) { + master_priv = dev->primary->master->driver_priv; + if (master_priv->sarea_priv) + master_priv->sarea_priv->last_dispatch = + READ_BREADCRUMB(dev_priv); + } - if (de_iir & DE_GSE) - ironlake_opregion_gse_intr(dev); + if (gt_iir & GT_USER_INTERRUPT) { + u32 seqno = i915_get_gem_seqno(dev); + dev_priv->mm.irq_gem_seqno = seqno; + trace_i915_gem_request_complete(dev, seqno); + DRM_WAKEUP(&dev_priv->irq_queue); + dev_priv->hangcheck_count = 0; + mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); + } - /* check event from PCH */ - if ((de_iir & DE_PCH_EVENT) && - (pch_iir & SDE_HOTPLUG_MASK)) { - queue_work(dev_priv->wq, &dev_priv->hotplug_work); - } + if (de_iir & DE_GSE) + ironlake_opregion_gse_intr(dev); - de_iir = new_de_iir; - gt_iir = new_gt_iir; - pch_iir = new_pch_iir; + /* check event from PCH */ + if ((de_iir & DE_PCH_EVENT) && + (pch_iir & SDE_HOTPLUG_MASK)) { + queue_work(dev_priv->wq, &dev_priv->hotplug_work); } + /* should clear PCH hotplug event before clear CPU irq */ + I915_WRITE(SDEIIR, pch_iir); + I915_WRITE(GTIIR, gt_iir); + I915_WRITE(DEIIR, de_iir); + +done: I915_WRITE(DEIER, de_ier); (void)I915_READ(DEIER); -- cgit v1.2.3-70-g09d2 From 6036ae7e9486352d5d1cbbee89186986e28e11fd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 15 Jan 2010 13:04:48 -0800 Subject: drm/i915: Remove chatty execbuf failure message. Suggested-by: Chris Wilson > Acked-by: Jesse Barnes (in principle) Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0f4afa3b03f..0c67924ca80 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4051,8 +4051,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, "back to user (%d)\n", args->buffer_count, ret); } - } else { - DRM_ERROR("i915_gem_do_execbuffer returns %d\n", ret); } drm_free_large(exec_list); -- cgit v1.2.3-70-g09d2 From 21bd770b9c90ee6a53a9dbb6293513a8c7654cfe Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 13 Jan 2010 14:10:50 +0000 Subject: drm/i915: Fix the incorrect cursor A bit definition in DSPFW2 register Signed-off-by: Zhao Yakui Reviewed-by: Eric Anholt Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 149d360d64a..847006c5218 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1815,7 +1815,7 @@ #define DSPFW_PLANEB_SHIFT 8 #define DSPFW2 0x70038 #define DSPFW_CURSORA_MASK 0x00003f00 -#define DSPFW_CURSORA_SHIFT 16 +#define DSPFW_CURSORA_SHIFT 8 #define DSPFW3 0x7003c #define DSPFW_HPLL_SR_EN (1<<31) #define DSPFW_CURSOR_SR_SHIFT 24 -- cgit v1.2.3-70-g09d2 From 33814341f22f13cec17e8d7fbf6f7e8000e3efa4 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 14 Jan 2010 20:48:02 +0000 Subject: drm/i915: disable LVDS downclock by default Many platform support this feature, and it can provide significant power savings when the reduced refresh rate is low. However, on some platforms a secondary (reduced) timing is provided but not actually supported by the hardware. This results in undesirable flicker at runtime. So disable the feature by default, but allow users to opt-in to the reduced clock behavior with a new module parameter, lvds_downclock, that can be set to 1 to enable the feature. Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.c | 3 +++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_bios.c | 3 ++- drivers/gpu/drm/i915/intel_lvds.c | 3 ++- 4 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 66f7bac2ee5..46d88965852 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -45,6 +45,9 @@ module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); unsigned int i915_powersave = 1; module_param_named(powersave, i915_powersave, int, 0400); +unsigned int i915_lvds_downclock = 0; +module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); + static struct drm_driver driver; #define INTEL_VGA_DEVICE(id, info) { \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 445c49c6c39..5f781a74bf5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -722,6 +722,7 @@ extern struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc; extern unsigned int i915_powersave; +extern unsigned int i915_lvds_downclock; extern void i915_save_display(struct drm_device *dev); extern void i915_restore_display(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index f2756774758..b53c46f202f 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -197,7 +197,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, memset(temp_mode, 0, sizeof(*temp_mode)); } kfree(temp_mode); - if (temp_downclock < panel_fixed_mode->clock) { + if (temp_downclock < panel_fixed_mode->clock && + i915_lvds_downclock) { dev_priv->lvds_downclock_avail = 1; dev_priv->lvds_downclock = temp_downclock; DRM_DEBUG_KMS("LVDS downclock is found in VBT. ", diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 5041590dfdc..aa74e59bec6 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -926,7 +926,8 @@ static void intel_find_lvds_downclock(struct drm_device *dev, } } mutex_unlock(&dev->mode_config.mutex); - if (temp_downclock < panel_fixed_mode->clock) { + if (temp_downclock < panel_fixed_mode->clock && + i915_lvds_downclock) { /* We found the downclock for LVDS. */ dev_priv->lvds_downclock_avail = 1; dev_priv->lvds_downclock = temp_downclock; -- cgit v1.2.3-70-g09d2 From 500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0c Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 13 Jan 2010 11:19:52 +0800 Subject: drm/i915: parse eDP panel color depth from VBT block Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_bios.c | 32 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_bios.h | 40 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5f781a74bf5..2c1669488b5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -283,6 +283,7 @@ typedef struct drm_i915_private { unsigned int lvds_use_ssc:1; unsigned int edp_support:1; int lvds_ssc_freq; + int edp_bpp; struct notifier_block lid_notifier; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index b53c46f202f..15fbc1b5a83 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -33,6 +33,8 @@ #define SLAVE_ADDR1 0x70 #define SLAVE_ADDR2 0x72 +static int panel_type; + static void * find_section(struct bdb_header *bdb, int section_id) { @@ -128,6 +130,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, dev_priv->lvds_dither = lvds_options->pixel_dither; if (lvds_options->panel_type == 0xff) return; + panel_type = lvds_options->panel_type; lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); if (!lvds_lfp_data) @@ -405,6 +408,34 @@ parse_driver_features(struct drm_i915_private *dev_priv, dev_priv->render_reclock_avail = true; } +static void +parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) +{ + struct bdb_edp *edp; + + edp = find_section(bdb, BDB_EDP); + if (!edp) { + if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) { + DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported,\ + assume 18bpp panel color depth.\n"); + dev_priv->edp_bpp = 18; + } + return; + } + + switch ((edp->color_depth >> (panel_type * 2)) & 3) { + case EDP_18BPP: + dev_priv->edp_bpp = 18; + break; + case EDP_24BPP: + dev_priv->edp_bpp = 24; + break; + case EDP_30BPP: + dev_priv->edp_bpp = 30; + break; + } +} + static void parse_device_mapping(struct drm_i915_private *dev_priv, struct bdb_header *bdb) @@ -522,6 +553,7 @@ intel_init_bios(struct drm_device *dev) parse_sdvo_device_mapping(dev_priv, bdb); parse_device_mapping(dev_priv, bdb); parse_driver_features(dev_priv, bdb); + parse_edp(dev_priv, bdb); pci_unmap_rom(pdev, bios); diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 425ac9d7f72..4c18514f6f8 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -98,6 +98,7 @@ struct vbios_data { #define BDB_SDVO_LVDS_PNP_IDS 24 #define BDB_SDVO_LVDS_POWER_SEQ 25 #define BDB_TV_OPTIONS 26 +#define BDB_EDP 27 #define BDB_LVDS_OPTIONS 40 #define BDB_LVDS_LFP_DATA_PTRS 41 #define BDB_LVDS_LFP_DATA 42 @@ -426,6 +427,45 @@ struct bdb_driver_features { u8 custom_vbt_version; } __attribute__((packed)); +#define EDP_18BPP 0 +#define EDP_24BPP 1 +#define EDP_30BPP 2 +#define EDP_RATE_1_62 0 +#define EDP_RATE_2_7 1 +#define EDP_LANE_1 0 +#define EDP_LANE_2 1 +#define EDP_LANE_4 3 +#define EDP_PREEMPHASIS_NONE 0 +#define EDP_PREEMPHASIS_3_5dB 1 +#define EDP_PREEMPHASIS_6dB 2 +#define EDP_PREEMPHASIS_9_5dB 3 +#define EDP_VSWING_0_4V 0 +#define EDP_VSWING_0_6V 1 +#define EDP_VSWING_0_8V 2 +#define EDP_VSWING_1_2V 3 + +struct edp_power_seq { + u16 t3; + u16 t7; + u16 t9; + u16 t10; + u16 t12; +} __attribute__ ((packed)); + +struct edp_link_params { + u8 rate:4; + u8 lanes:4; + u8 preemphasis:4; + u8 vswing:4; +} __attribute__ ((packed)); + +struct bdb_edp { + struct edp_power_seq power_seqs[16]; + u32 color_depth; + u32 sdrrs_msa_timing_delay; + struct edp_link_params link_params[16]; +} __attribute__ ((packed)); + bool intel_init_bios(struct drm_device *dev); /* -- cgit v1.2.3-70-g09d2 From 885a5fb5b120a5c7e0b3baad7b0feb5a89f76c18 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 12 Jan 2010 05:38:31 +0800 Subject: drm/i915: fix pixel color depth setting on eDP Original DP mode_valid check didn't take pixel color depth into account, which made one 1600x900 eDP panel's mode check invalid because of overclock, but actually this 6bpc panel does can work with x1 lane at 2.7G. This one trys to take bpp value properly both in mode validation and mode setting. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 15 +++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 16 ++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4b96a54b8e4..45da78ef4a9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2924,6 +2924,21 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, temp |= PIPE_8BPC; else temp |= PIPE_6BPC; + } else if (is_edp) { + switch (dev_priv->edp_bpp/3) { + case 8: + temp |= PIPE_8BPC; + break; + case 10: + temp |= PIPE_10BPC; + break; + case 6: + temp |= PIPE_6BPC; + break; + case 12: + temp |= PIPE_12BPC; + break; + } } else temp |= PIPE_8BPC; I915_WRITE(pipeconf_reg, temp); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0ec07e43d6c..184b6780c44 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -125,9 +125,15 @@ intel_dp_link_clock(uint8_t link_bw) /* I think this is a fiction */ static int -intel_dp_link_required(int pixel_clock) +intel_dp_link_required(struct drm_device *dev, + struct intel_output *intel_output, int pixel_clock) { - return pixel_clock * 3; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (IS_eDP(intel_output)) + return (pixel_clock * dev_priv->edp_bpp) / 8; + else + return pixel_clock * 3; } static int @@ -138,7 +144,8 @@ intel_dp_mode_valid(struct drm_connector *connector, int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output)); int max_lanes = intel_dp_max_lane_count(intel_output); - if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes) + if (intel_dp_link_required(connector->dev, intel_output, mode->clock) + > max_link_clock * max_lanes) return MODE_CLOCK_HIGH; if (mode->clock < 10000) @@ -492,7 +499,8 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, for (clock = 0; clock <= max_clock; clock++) { int link_avail = intel_dp_link_clock(bws[clock]) * lane_count; - if (intel_dp_link_required(mode->clock) <= link_avail) { + if (intel_dp_link_required(encoder->dev, intel_output, mode->clock) + <= link_avail) { dp_priv->link_bw = bws[clock]; dp_priv->lane_count = lane_count; adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); -- cgit v1.2.3-70-g09d2 From 6251ec0ae2eb9e9e96689422358c2fdb35c63768 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 12 Jan 2010 05:38:32 +0800 Subject: drm/i915: fix eDP pipe mask eDP could be on pipe A or B. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_dp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 184b6780c44..439506cefc1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1331,11 +1331,10 @@ intel_dp_init(struct drm_device *dev, int output_reg) else if (output_reg == DP_D || output_reg == PCH_DP_D) intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT); - if (IS_eDP(intel_output)) { - intel_output->crtc_mask = (1 << 1); + if (IS_eDP(intel_output)) intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT); - } else - intel_output->crtc_mask = (1 << 0) | (1 << 1); + + intel_output->crtc_mask = (1 << 0) | (1 << 1); connector->interlace_allowed = true; connector->doublescan_allowed = 0; -- cgit v1.2.3-70-g09d2 From 9b974cc17166d31afed2638d56bdbf9829afbfaa Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 5 Jan 2010 11:25:06 +0800 Subject: drm/i915: enable 36bit physical address for hardware status page This enables possible 36bit address mask on 965G that use physical address for hw status page. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/char/agp/intel-agp.c | 6 +++++- drivers/gpu/drm/i915/i915_dma.c | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 30c36ac2cd0..3999a5f25f3 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -2460,10 +2460,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, &bridge->mode); } - if (bridge->driver->mask_memory == intel_i965_mask_memory) + if (bridge->driver->mask_memory == intel_i965_mask_memory) { if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36))) dev_err(&intel_private.pcidev->dev, "set gfx device dma mask 36bit failed!\n"); + else + pci_set_consistent_dma_mask(intel_private.pcidev, + DMA_BIT_MASK(36)); + } pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index bbe47812e4b..e660ac07f3b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -134,6 +134,10 @@ static int i915_init_phys_hws(struct drm_device *dev) memset(dev_priv->hw_status_page, 0, PAGE_SIZE); + if (IS_I965G(dev)) + dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & + 0xf0; + I915_WRITE(HWS_PGA, dev_priv->dma_status_page); DRM_DEBUG_DRIVER("Enabled hardware status page\n"); return 0; -- cgit v1.2.3-70-g09d2 From f5347867c5aea94c625246eaff8f7820b0a4cd8a Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 30 Dec 2009 15:53:03 +0300 Subject: ACPI: SBS: Move SBS HC callback to faster Notify queue SBS transactions should happen in Notify work queue, to not create a dead lock with GPE execution accessing SBS devices. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 3 ++- drivers/acpi/sbshc.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 9cc38857c33..04733092982 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -535,7 +535,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec) return -ENOMEM; memcpy(copy, handler, sizeof(*copy)); pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); - return acpi_os_execute(OSL_GPE_HANDLER, + return acpi_os_execute((copy->func) ? + OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, acpi_ec_run, copy); } } diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index d9339806df4..fd09229282e 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -242,7 +242,7 @@ static int smbus_alarm(void *context) case ACPI_SBS_CHARGER: case ACPI_SBS_MANAGER: case ACPI_SBS_BATTERY: - acpi_os_execute(OSL_GPE_HANDLER, + acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_smbus_callback, hc); default:; } -- cgit v1.2.3-70-g09d2 From 54070101f86ca9a6e9ba243c999d144721ec3db7 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 30 Dec 2009 15:53:10 +0300 Subject: ACPI: EC: Add wait for irq storm Merge of poll and irq modes accelerated EC transaction, so that keyboard starts to suffer again. Add msleep(1) into transaction path for the storm to allow keyboard controller to do its job. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14747 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 04733092982..d6471bb6852 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -259,7 +259,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); spin_unlock_irqrestore(&ec->curr_lock, tmp); ret = ec_poll(ec); - pr_debug(PREFIX "transaction end\n"); spin_lock_irqsave(&ec->curr_lock, tmp); ec->curr = NULL; spin_unlock_irqrestore(&ec->curr_lock, tmp); @@ -316,6 +315,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) /* check if we received SCI during transaction */ ec_check_sci_sync(ec, acpi_ec_read_status(ec)); if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + msleep(1); /* it is safe to enable GPE outside of transaction */ acpi_enable_gpe(NULL, ec->gpe); } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { @@ -323,6 +323,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) "transactions will use polling mode\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } + pr_debug(PREFIX "transaction end\n"); end: if (ec->global_lock) acpi_release_global_lock(glk); -- cgit v1.2.3-70-g09d2 From 6a4e2b7503d1f630bface040cf0f5a7aac1fabdb Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 21:29:58 +0800 Subject: ACPI: Advertise to BIOS in _OSC: _OST on _PPC changes If the BIOS pokes the system-wide OSC bits to see if Linux supports evaluating _OST after a _PPC change notification, answer yes. Also, fix an oversight where we neglected to set the OSC bit advertising processor aggregator device support when acpi-pad is compiled as a module. Signed-off-by: Zhao Yakui Signed-off-by: Len Brown --- drivers/acpi/bus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index cf761b904e4..a52126e4630 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -490,9 +490,14 @@ static void acpi_bus_osc_support(void) capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ -#ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR +#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ + defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; #endif + +#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) + capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; +#endif if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) -- cgit v1.2.3-70-g09d2 From 070a24f4d238612bede515023893b18f494774c4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 8 Jan 2010 11:12:41 -0700 Subject: ACPI: Remove unnecessary cast. The struct seq_file 'private' member is a void *, the cast is not needed. Also, remove an extra whitespace line. Signed-off-by: H Hartley Sweeten Signed-off-by: Len Brown --- drivers/acpi/processor_thermal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 140c5c5b423..6deafb4aa0d 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -443,8 +443,7 @@ struct thermal_cooling_device_ops processor_cooling_ops = { #ifdef CONFIG_ACPI_PROCFS static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) { - struct acpi_processor *pr = (struct acpi_processor *)seq->private; - + struct acpi_processor *pr = seq->private; if (!pr) goto end; -- cgit v1.2.3-70-g09d2 From da8ba01deb98f3dc0558b1f5a37e64f40bba7904 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Wed, 6 Jan 2010 22:07:37 +0100 Subject: eeepc-laptop: disable cpu speed control on EeePC 701 The EeePC 4G ("701") implements CFVS, but it is not supported by the pre-installed OS, and the original option to change it in the BIOS setup screen was removed in later versions. Judging by the lack of "Super Hybrid Engine" on Asus product pages, this applies to all "701" models (4G/4G Surf/2G Surf). So Asus made a deliberate decision not to support it on this model. We have several reports that using it can cause the system to hang [1]. That said, it does not happen all the time. Some users do not experience it at all (and apparently wish to continue "right-clocking"). Check for the EeePC 701 using DMI. If met, then disable writes to the "cpufv" sysfs attribute and log an explanatory message. Add a "cpufv_disabled" attribute which allow users to override this policy. Writing to this attribute will log a second message. The sysfs attribute is more useful than a module option, because it makes it easier for userspace scripts to provide consistent behaviour (according to user configuration), regardless of whether the kernel includes this change. [1] Signed-off-by: Alan Jenkins Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 5838c69b2fb..e954f2af572 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -35,6 +35,7 @@ #include #include #include +#include #define EEEPC_LAPTOP_VERSION "0.1" #define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver" @@ -159,6 +160,7 @@ struct eeepc_laptop { acpi_handle handle; /* the handle of the acpi device */ u32 cm_supported; /* the control methods supported by this BIOS */ + bool cpufv_disabled; u16 event_count[128]; /* count for each event */ struct platform_device *platform_device; @@ -378,6 +380,8 @@ static ssize_t store_cpufv(struct device *dev, struct eeepc_cpufv c; int rv, value; + if (eeepc->cpufv_disabled) + return -EPERM; if (get_cpufv(eeepc, &c)) return -ENODEV; rv = parse_arg(buf, count, &value); @@ -389,6 +393,41 @@ static ssize_t store_cpufv(struct device *dev, return rv; } +static ssize_t show_cpufv_disabled(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct eeepc_laptop *eeepc = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", eeepc->cpufv_disabled); +} + +static ssize_t store_cpufv_disabled(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct eeepc_laptop *eeepc = dev_get_drvdata(dev); + int rv, value; + + rv = parse_arg(buf, count, &value); + if (rv < 0) + return rv; + + switch (value) { + case 0: + if (eeepc->cpufv_disabled) + pr_warning("cpufv enabled (not officially supported " + "on this model)\n"); + eeepc->cpufv_disabled = false; + return rv; + case 1: + return -EPERM; + default: + return -EINVAL; + } +} + + static struct device_attribute dev_attr_cpufv = { .attr = { .name = "cpufv", @@ -404,12 +443,22 @@ static struct device_attribute dev_attr_available_cpufv = { .show = show_available_cpufv }; +static struct device_attribute dev_attr_cpufv_disabled = { + .attr = { + .name = "cpufv_disabled", + .mode = 0644 }, + .show = show_cpufv_disabled, + .store = store_cpufv_disabled +}; + + static struct attribute *platform_attributes[] = { &dev_attr_camera.attr, &dev_attr_cardr.attr, &dev_attr_disp.attr, &dev_attr_cpufv.attr, &dev_attr_available_cpufv.attr, + &dev_attr_cpufv_disabled.attr, NULL }; @@ -1261,6 +1310,42 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event) } } +static void eeepc_dmi_check(struct eeepc_laptop *eeepc) +{ + const char *model; + + /* + * Blacklist for setting cpufv (cpu speed). + * + * EeePC 4G ("701") implements CFVS, but it is not supported + * by the pre-installed OS, and the original option to change it + * in the BIOS setup screen was removed in later versions. + * + * Judging by the lack of "Super Hybrid Engine" on Asus product pages, + * this applies to all "701" models (4G/4G Surf/2G Surf). + * + * So Asus made a deliberate decision not to support it on this model. + * We have several reports that using it can cause the system to hang + * + * The hang has also been reported on a "702" (Model name "8G"?). + * + * We avoid dmi_check_system() / dmi_match(), because they use + * substring matching. We don't want to affect the "701SD" + * and "701SDX" models, because they do support S.H.E. + */ + + model = dmi_get_system_info(DMI_PRODUCT_NAME); + if (!model) + return; + + if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { + eeepc->cpufv_disabled = true; + pr_info("model %s does not officially support setting cpu " + "speed\n", model); + pr_info("cpufv disabled to avoid instability\n"); + } +} + static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name) { int dummy; @@ -1342,6 +1427,8 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device) strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); device->driver_data = eeepc; + eeepc_dmi_check(eeepc); + result = eeepc_acpi_init(eeepc, device); if (result) goto fail_platform; -- cgit v1.2.3-70-g09d2 From 10ae4b5663ff3092553bfbd867e7bd474ce6c553 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 6 Jan 2010 22:07:38 +0100 Subject: eeepc-laptop: dmi blacklist to disable pci hotplug code This is a short term workaround for Eeepc 1005HA. refs: Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index e954f2af572..7fc944ac207 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -161,6 +161,7 @@ struct eeepc_laptop { u32 cm_supported; /* the control methods supported by this BIOS */ bool cpufv_disabled; + bool hotplug_disabled; u16 event_count[128]; /* count for each event */ struct platform_device *platform_device; @@ -845,6 +846,9 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc) if (result && result != -ENODEV) goto exit; + if (eeepc->hotplug_disabled) + return 0; + result = eeepc_setup_pci_hotplug(eeepc); /* * If we get -EBUSY then something else is handling the PCI hotplug - @@ -1314,6 +1318,10 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc) { const char *model; + model = dmi_get_system_info(DMI_PRODUCT_NAME); + if (!model) + return; + /* * Blacklist for setting cpufv (cpu speed). * @@ -1333,17 +1341,24 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc) * substring matching. We don't want to affect the "701SD" * and "701SDX" models, because they do support S.H.E. */ - - model = dmi_get_system_info(DMI_PRODUCT_NAME); - if (!model) - return; - if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { eeepc->cpufv_disabled = true; pr_info("model %s does not officially support setting cpu " "speed\n", model); pr_info("cpufv disabled to avoid instability\n"); } + + /* + * Blacklist for wlan hotplug + * + * Eeepc 1005HA doesn't work like others models and don't need the + * hotplug code. In fact, current hotplug code seems to unplug another + * device... + */ + if (strcmp(model, "1005HA") == 0) { + eeepc->hotplug_disabled = true; + pr_info("wlan hotplug disabled\n"); + } } static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name) -- cgit v1.2.3-70-g09d2 From 642e0447cb910ceabae0b4ea6c0cd3449d5c5abb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 6 Jan 2010 22:07:39 +0100 Subject: eeepc-laptop: switch to using sparse keymap library Signed-off-by: Dmitry Torokhov Tested-by: Alan Jenkins Acked-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/eeepc-laptop.c | 186 ++++++++++-------------------------- 2 files changed, 52 insertions(+), 135 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index db32c25e360..f526e735c5a 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -364,6 +364,7 @@ config EEEPC_LAPTOP select HWMON select LEDS_CLASS select NEW_LEDS + select INPUT_SPARSEKMAP ---help--- This driver supports the Fn-Fx keys on Eee PC laptops. diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 7fc944ac207..07d7978c558 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -121,38 +122,28 @@ static const char *cm_setv[] = { NULL, NULL, "PBPS", "TPDS" }; -struct key_entry { - char type; - u8 code; - u16 keycode; -}; - -enum { KE_KEY, KE_END }; - static const struct key_entry eeepc_keymap[] = { - /* Sleep already handled via generic ACPI code */ - {KE_KEY, 0x10, KEY_WLAN }, - {KE_KEY, 0x11, KEY_WLAN }, - {KE_KEY, 0x12, KEY_PROG1 }, - {KE_KEY, 0x13, KEY_MUTE }, - {KE_KEY, 0x14, KEY_VOLUMEDOWN }, - {KE_KEY, 0x15, KEY_VOLUMEUP }, - {KE_KEY, 0x16, KEY_DISPLAY_OFF }, - {KE_KEY, 0x1a, KEY_COFFEE }, - {KE_KEY, 0x1b, KEY_ZOOM }, - {KE_KEY, 0x1c, KEY_PROG2 }, - {KE_KEY, 0x1d, KEY_PROG3 }, - {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, - {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP }, - {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, - {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, - {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, - {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */ - {KE_KEY, 0x38, KEY_F14 }, - {KE_END, 0}, + { KE_KEY, 0x10, { KEY_WLAN } }, + { KE_KEY, 0x11, { KEY_WLAN } }, + { KE_KEY, 0x12, { KEY_PROG1 } }, + { KE_KEY, 0x13, { KEY_MUTE } }, + { KE_KEY, 0x14, { KEY_VOLUMEDOWN } }, + { KE_KEY, 0x15, { KEY_VOLUMEUP } }, + { KE_KEY, 0x16, { KEY_DISPLAY_OFF } }, + { KE_KEY, 0x1a, { KEY_COFFEE } }, + { KE_KEY, 0x1b, { KEY_ZOOM } }, + { KE_KEY, 0x1c, { KEY_PROG2 } }, + { KE_KEY, 0x1d, { KEY_PROG3 } }, + { KE_KEY, NOTIFY_BRN_MIN, { KEY_BRIGHTNESSDOWN } }, + { KE_KEY, NOTIFY_BRN_MAX, { KEY_BRIGHTNESSUP } }, + { KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */ + { KE_KEY, 0x38, { KEY_F14 } }, + { KE_END, 0 }, }; - /* * This is the main structure, we can use it to store useful information */ @@ -1143,120 +1134,42 @@ static void eeepc_backlight_exit(struct eeepc_laptop *eeepc) /* * Input device (i.e. hotkeys) */ -static struct key_entry *eeepc_get_entry_by_scancode( - struct eeepc_laptop *eeepc, - int code) +static int eeepc_input_init(struct eeepc_laptop *eeepc) { - struct key_entry *key; - - for (key = eeepc->keymap; key->type != KE_END; key++) - if (code == key->code) - return key; + struct input_dev *input; + int error; - return NULL; -} - -static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event) -{ - static struct key_entry *key; - - key = eeepc_get_entry_by_scancode(eeepc, event); - if (key) { - switch (key->type) { - case KE_KEY: - input_report_key(eeepc->inputdev, key->keycode, - 1); - input_sync(eeepc->inputdev); - input_report_key(eeepc->inputdev, key->keycode, - 0); - input_sync(eeepc->inputdev); - break; - } + input = input_allocate_device(); + if (!input) { + pr_info("Unable to allocate input device\n"); + return -ENOMEM; } -} - -static struct key_entry *eeepc_get_entry_by_keycode( - struct eeepc_laptop *eeepc, int code) -{ - struct key_entry *key; - - for (key = eeepc->keymap; key->type != KE_END; key++) - if (code == key->keycode && key->type == KE_KEY) - return key; - return NULL; -} + input->name = "Asus EeePC extra buttons"; + input->phys = EEEPC_LAPTOP_FILE "/input0"; + input->id.bustype = BUS_HOST; + input->dev.parent = &eeepc->platform_device->dev; -static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) -{ - struct eeepc_laptop *eeepc = input_get_drvdata(dev); - struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode); - - if (key && key->type == KE_KEY) { - *keycode = key->keycode; - return 0; + error = sparse_keymap_setup(input, eeepc_keymap, NULL); + if (error) { + pr_err("Unable to setup input device keymap\n"); + goto err_free_dev; } - return -EINVAL; -} - -static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) -{ - struct eeepc_laptop *eeepc = input_get_drvdata(dev); - struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - - key = eeepc_get_entry_by_scancode(eeepc, scancode); - if (key && key->type == KE_KEY) { - old_keycode = key->keycode; - key->keycode = keycode; - set_bit(keycode, dev->keybit); - if (!eeepc_get_entry_by_keycode(eeepc, old_keycode)) - clear_bit(old_keycode, dev->keybit); - return 0; + error = input_register_device(input); + if (error) { + pr_err("Unable to register input device\n"); + goto err_free_keymap; } - return -EINVAL; -} - -static int eeepc_input_init(struct eeepc_laptop *eeepc) -{ - const struct key_entry *key; - int result; - - eeepc->inputdev = input_allocate_device(); - if (!eeepc->inputdev) { - pr_info("Unable to allocate input device\n"); - return -ENOMEM; - } - eeepc->inputdev->name = "Asus EeePC extra buttons"; - eeepc->inputdev->dev.parent = &eeepc->platform_device->dev; - eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0"; - eeepc->inputdev->id.bustype = BUS_HOST; - eeepc->inputdev->getkeycode = eeepc_getkeycode; - eeepc->inputdev->setkeycode = eeepc_setkeycode; - input_set_drvdata(eeepc->inputdev, eeepc); - - eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap), - GFP_KERNEL); - for (key = eeepc_keymap; key->type != KE_END; key++) { - switch (key->type) { - case KE_KEY: - set_bit(EV_KEY, eeepc->inputdev->evbit); - set_bit(key->keycode, eeepc->inputdev->keybit); - break; - } - } - result = input_register_device(eeepc->inputdev); - if (result) { - pr_info("Unable to register input device\n"); - input_free_device(eeepc->inputdev); - return result; - } + eeepc->inputdev = input; return 0; + + err_free_keymap: + sparse_keymap_free(input); + err_free_dev: + input_free_device(input); + return error; } static void eeepc_input_exit(struct eeepc_laptop *eeepc) @@ -1306,11 +1219,12 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event) * event will be desired value (or else ignored) */ } - eeepc_input_notify(eeepc, event); + sparse_keymap_report_event(eeepc->inputdev, event, + 1, true); } } else { /* Everything else is a bona-fide keypress event */ - eeepc_input_notify(eeepc, event); + sparse_keymap_report_event(eeepc->inputdev, event, 1, true); } } @@ -1554,10 +1468,12 @@ static int __init eeepc_laptop_init(void) result = acpi_bus_register_driver(&eeepc_acpi_driver); if (result < 0) goto fail_acpi_driver; + if (!eeepc_device_present) { result = -ENODEV; goto fail_no_device; } + return 0; fail_no_device: -- cgit v1.2.3-70-g09d2 From 322a1356be96bcc4b97e8e370f6468c821330077 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 6 Jan 2010 22:07:40 +0100 Subject: eeepc-laptop: add hotplug_disable parameter Some new models need to disable wireless hotplug. For the moment, we don't know excactly what models need that, except 1005HA. Users will be able to use that param as a workaround. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 07d7978c558..a959abdea3a 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -50,6 +50,14 @@ MODULE_AUTHOR("Corentin Chary, Eric Cooper"); MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME); MODULE_LICENSE("GPL"); +static bool hotplug_disabled; + +module_param(hotplug_disabled, bool, 0644); +MODULE_PARM_DESC(hotplug_disabled, + "Disable hotplug for wireless device. " + "If your laptop need that, please report to " + "acpi4asus-user@lists.sourceforge.net."); + /* * Definitions for Asus EeePC */ @@ -1356,6 +1364,8 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device) strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); device->driver_data = eeepc; + eeepc->hotplug_disabled = hotplug_disabled; + eeepc_dmi_check(eeepc); result = eeepc_acpi_init(eeepc, device); -- cgit v1.2.3-70-g09d2 From 4194e2f551a6308e6ab34ac88210bf54858aa7df Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 6 Jan 2010 22:07:41 +0100 Subject: eeepc-laptop: disable wireless hotplug for 1201N Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index a959abdea3a..e2be6bb33d9 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -1277,7 +1277,7 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc) * hotplug code. In fact, current hotplug code seems to unplug another * device... */ - if (strcmp(model, "1005HA") == 0) { + if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) { eeepc->hotplug_disabled = true; pr_info("wlan hotplug disabled\n"); } -- cgit v1.2.3-70-g09d2 From 7a0b73a49ab56fb1e836675c00d6d0d2ba39a714 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Mon, 28 Dec 2009 10:39:23 -0800 Subject: ACPI: Fix section mismatch error for acpi_early_processor_set_pdc() Alex Chiang introduced acpi_early_processor_set_pdc() in commit: ACPI: processor: call _PDC early 78f1699659963fff97975df44db6d5dbe7218e55 But this results in a section mismatch: WARNING: drivers/acpi/acpi.o(.text+0xa9c1): Section mismatch in reference from the function acpi_early_processor_set_pdc() to the variable .cpuinit.data:processor_idle_dmi_table The function acpi_early_processor_set_pdc() references the variable __cpuinitdata processor_idle_dmi_table. This is often because acpi_early_processor_set_pdc lacks a __cpuinitdata annotation or the annotation of processor_idle_dmi_table is wrong. The only caller of acpi_early_processor_set_pdc() is acpi_bus_init() which is an "__init" function. So the correct fix here is to mark acpi_early_processor_set_pdc() "__init" too. Signed-off-by: Tony Luck Acked-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 30e4dc0cdf3..7d4ee394d0b 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -151,7 +151,7 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -void acpi_early_processor_set_pdc(void) +void __init acpi_early_processor_set_pdc(void) { /* * Check whether the system is DMI table. If yes, OSPM -- cgit v1.2.3-70-g09d2 From 0b2c3688445ff02d3f1bfffc6983417b28f8c3da Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sat, 16 Jan 2010 20:43:12 +0100 Subject: i2c-core: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0ac2f90ab84..d610e995bbf 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -248,7 +248,7 @@ static const struct attribute_group *i2c_dev_attr_groups[] = { NULL }; -const static struct dev_pm_ops i2c_device_pm_ops = { +static const struct dev_pm_ops i2c_device_pm_ops = { .suspend = i2c_device_pm_suspend, .resume = i2c_device_pm_resume, }; -- cgit v1.2.3-70-g09d2 From b6a3195070fe1c12d0bb1099ffe997d8abf9f602 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 16 Jan 2010 20:43:12 +0100 Subject: i2c: Test off by one in {piix4,vt596}_transaction() With `while (timeout++ < MAX_TIMEOUT)' timeout reaches MAX_TIMEOUT + 1 after the loop. This is probably unlikely to produce a problem. Signed-off-by: Roel Kluin Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-piix4.c | 4 ++-- drivers/i2c/busses/i2c-viapro.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 1e245e9cad3..e56e4b6823c 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -324,12 +324,12 @@ static int piix4_transaction(void) else msleep(1); - while ((timeout++ < MAX_TIMEOUT) && + while ((++timeout < MAX_TIMEOUT) && ((temp = inb_p(SMBHSTSTS)) & 0x01)) msleep(1); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout == MAX_TIMEOUT) { dev_err(&piix4_adapter.dev, "SMBus Timeout!\n"); result = -ETIMEDOUT; } diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index e4b1543015a..a84a909e123 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -165,10 +165,10 @@ static int vt596_transaction(u8 size) do { msleep(1); temp = inb_p(SMBHSTSTS); - } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); + } while ((temp & 0x01) && (++timeout < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout == MAX_TIMEOUT) { result = -ETIMEDOUT; dev_err(&vt596_adapter.dev, "SMBus timeout!\n"); } -- cgit v1.2.3-70-g09d2 From 7d53e79f9ec2842269754efbe34f53aa480d99e3 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sat, 16 Jan 2010 20:43:13 +0100 Subject: i2c-ali1563: Remove sparse warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the following sparse warnings (see "make C=1"): * drivers/i2c/busses/i2c-ali1563.c:91:3: warning: do-while statement is not a compound statement * drivers/i2c/busses/i2c-ali1563.c:161:3: warning: do-while statement is not a compound statement Signed-off-by: Márton Németh Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-ali1563.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index f70f46582c6..4687af40dd5 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c @@ -87,9 +87,9 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2); timeout = ALI1563_MAX_TIMEOUT; - do + do { msleep(1); - while (((data = inb_p(SMB_HST_STS)) & HST_STS_BUSY) && --timeout); + } while (((data = inb_p(SMB_HST_STS)) & HST_STS_BUSY) && --timeout); dev_dbg(&a->dev, "Transaction (post): STS=%02x, CNTL1=%02x, " "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", @@ -157,9 +157,9 @@ static int ali1563_block_start(struct i2c_adapter * a) outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2); timeout = ALI1563_MAX_TIMEOUT; - do + do { msleep(1); - while (!((data = inb_p(SMB_HST_STS)) & HST_STS_DONE) && --timeout); + } while (!((data = inb_p(SMB_HST_STS)) & HST_STS_DONE) && --timeout); dev_dbg(&a->dev, "Block (post): STS=%02x, CNTL1=%02x, " "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", -- cgit v1.2.3-70-g09d2 From 22f8b2695eda496026623020811cae34590ee3d7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 16 Jan 2010 20:43:13 +0100 Subject: i2c/pca: Don't use *_interruptible Unexpected signals can disturb the bus-handling and lock it up. Don't use interruptible in 'wait_event_*' and 'wake_*' as in commits dc1972d02747d2170fb1d78d114801f5ecb27506 (for cpm), 1ab082d7cbd0f34e39a5396cc6340c00bc5d66ef (for mpc), b7af349b175af45f9d87b3bf3f0a221e1831ed39 (for omap). Signed-off-by: Wolfram Sang Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-pca-isa.c | 4 ++-- drivers/i2c/busses/i2c-pca-platform.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index 0ed68e2ccd2..f7346a9bd95 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -75,7 +75,7 @@ static int pca_isa_waitforcompletion(void *pd) unsigned long timeout; if (irq > -1) { - ret = wait_event_interruptible_timeout(pca_wait, + ret = wait_event_timeout(pca_wait, pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI, pca_isa_ops.timeout); } else { @@ -96,7 +96,7 @@ static void pca_isa_resetchip(void *pd) } static irqreturn_t pca_handler(int this_irq, void *dev_id) { - wake_up_interruptible(&pca_wait); + wake_up(&pca_wait); return IRQ_HANDLED; } diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index c4df9d411cd..5b2213df5ed 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -84,7 +84,7 @@ static int i2c_pca_pf_waitforcompletion(void *pd) unsigned long timeout; if (i2c->irq) { - ret = wait_event_interruptible_timeout(i2c->wait, + ret = wait_event_timeout(i2c->wait, i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI, i2c->adap.timeout); } else { @@ -122,7 +122,7 @@ static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id) if ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) return IRQ_NONE; - wake_up_interruptible(&i2c->wait); + wake_up(&i2c->wait); return IRQ_HANDLED; } -- cgit v1.2.3-70-g09d2 From c556752109794a5ff199b80a1673336b4df8433a Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Sat, 16 Jan 2010 20:43:13 +0100 Subject: i2c: Do not use device name after device_unregister MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dev_dbg outputs dev_name, which is released with device_unregister. This bug resulted in output like this: i2c Xy2�0: adapter [SMBus I801 adapter at 1880] unregistered The right output would be: i2c i2c-0: adapter [SMBus I801 adapter at 1880] unregistered Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index d610e995bbf..10be7b5fbe9 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -843,6 +843,9 @@ int i2c_del_adapter(struct i2c_adapter *adap) adap->dev.parent); #endif + /* device name is gone after device_unregister */ + dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); + /* clean up the sysfs representation */ init_completion(&adap->dev_released); device_unregister(&adap->dev); @@ -855,8 +858,6 @@ int i2c_del_adapter(struct i2c_adapter *adap) idr_remove(&i2c_adapter_idr, adap->nr); mutex_unlock(&core_lock); - dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); - /* Clear the device structure in case this adapter is ever going to be added again */ memset(&adap->dev, 0, sizeof(adap->dev)); -- cgit v1.2.3-70-g09d2 From 0b94190e1e60f96962b82d35729d7d44cf298ef8 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Fri, 15 Jan 2010 17:01:03 -0800 Subject: viafb: fix LCD hardware cursor regression Although I'd consider this a hardware bug, as there is hardware out that for whatever reason does not support hardware cursors on LCD output we have to care about it in the driver. This fixes a regression (invisible cursor) introduced by: viafb: cleanup viafb_cursor Signed-off-by: Florian Tobias Schandinat Reported-by: Julian Wollrath Tested-by: Julian Wollrath Cc: Scott Fang Cc: Joseph Chan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/via/viafbdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index d8df17a7d5f..a0004c17af6 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -872,7 +872,9 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo) return -ENODEV; - if (chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) + /* LCD ouput does not support hw cursors (at least on VN896) */ + if ((chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) || + viafb_LCD_ON) return -ENODEV; viafb_show_hw_cursor(info, HW_Cursor_OFF); -- cgit v1.2.3-70-g09d2 From 8a3a95c32f612068be8dae74fa5fc4cf2db1592e Mon Sep 17 00:00:00 2001 From: Erik-Jan Post Date: Fri, 15 Jan 2010 17:01:05 -0800 Subject: viafb: do modesetting after updating variables Reorder viafb_set_par to allow using the updated variables in viafb_setmode. This fixes a regression that prevented proper runtime mode changes. Signed-off-by: Erik-Jan Post Signed-off-by: Florian Tobias Schandinat Cc: Scott Fang Cc: Joseph Chan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/via/viafbdev.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index a0004c17af6..3028e7ddc3b 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -177,16 +177,15 @@ static int viafb_set_par(struct fb_info *info) } if (vmode_index != VIA_RES_INVALID) { - viafb_setmode(vmode_index, info->var.xres, info->var.yres, - info->var.bits_per_pixel, vmode_index1, - viafb_second_xres, viafb_second_yres, viafb_bpp1); - viafb_update_fix(info); viafb_bpp = info->var.bits_per_pixel; if (info->var.accel_flags & FB_ACCELF_TEXT) info->flags &= ~FBINFO_HWACCEL_DISABLED; else info->flags |= FBINFO_HWACCEL_DISABLED; + viafb_setmode(vmode_index, info->var.xres, info->var.yres, + info->var.bits_per_pixel, vmode_index1, + viafb_second_xres, viafb_second_yres, viafb_bpp1); } return 0; -- cgit v1.2.3-70-g09d2 From 97922b5462fa543484831d42ab0fe4562b9373fc Mon Sep 17 00:00:00 2001 From: Erik-Jan Post Date: Fri, 15 Jan 2010 17:01:06 -0800 Subject: viafb: fix acceleration for some chips Fix a regression in hardware acceleration which made the accelerated framebuffer unusable on some chips. These need extra initialization and an extra flag which is no longer needed/available on current chips. Signed-off-by: Erik-Jan Post Signed-off-by: Florian Tobias Schandinat Cc: Scott Fang Cc: Joseph Chan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/via/accel.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index 9d4f3a49ba4..d5077dfa9e0 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -137,7 +137,7 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, tmp, dst_pitch); return -EINVAL; } - tmp = (tmp >> 3) | (dst_pitch << (16 - 3)); + tmp = VIA_PITCH_ENABLE | (tmp >> 3) | (dst_pitch << (16 - 3)); writel(tmp, engine + 0x38); if (op == VIA_BITBLT_FILL) @@ -352,6 +352,9 @@ int viafb_init_engine(struct fb_info *info) viapar->shared->vq_vram_addr = viapar->fbmem_free; viapar->fbmem_used += VQ_SIZE; + /* Init 2D engine reg to reset 2D engine */ + writel(0x0, engine + VIA_REG_KEYCONTROL); + /* Init AGP and VQ regs */ switch (chip_name) { case UNICHROME_K8M890: -- cgit v1.2.3-70-g09d2 From 3018aa4b1a46946dfd0ee73a533038f24e390539 Mon Sep 17 00:00:00 2001 From: Ping Date: Fri, 15 Jan 2010 17:01:07 -0800 Subject: serial/8250_pnp: add a new Fujitsu Wacom Tablet PC device This is a new two finger touch Fujitsu Wacom Tablet PC. Signed-off-by: Ping Cheng Cc: Alan Cox Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/8250_pnp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 36ede02ceac..b5496a19d96 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -354,6 +354,8 @@ static const struct pnp_device_id pnp_dev_table[] = { { "FUJ02E5", 0 }, /* Fujitsu P-series tablet PC device */ { "FUJ02E6", 0 }, + /* Fujitsu Wacom 2FGT Tablet PC device */ + { "FUJ02E7", 0 }, /* * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in * disguise) -- cgit v1.2.3-70-g09d2 From 118f3e1afd5534c15f9701f33514186cfc841a27 Mon Sep 17 00:00:00 2001 From: Tamas Vincze Date: Fri, 15 Jan 2010 17:01:10 -0800 Subject: edac: i5000_edac critical fix panic out of bounds EDAC MC0: INTERNAL ERROR: channel-b out of range (4 >= 4) Kernel panic - not syncing: EDAC MC0: Uncorrected Error (XEN) Domain 0 crashed: 'noreboot' set - not rebooting. This happens because FERR_NF_FBD bit 28 is not updated on i5000. Due to that, both bits 28 and 29 may be equal to one, returning channel = 3. As this value is invalid, EDAC core generates the panic. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=14568 Signed-off-by: Tamas Vincze Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Doug Thompson Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/i5000_edac.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 77a9579d716..adc10a2ac5f 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -577,7 +577,13 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, debugf0("\tUncorrected bits= 0x%x\n", ue_errors); branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd); - channel = branch; + + /* + * According with i5000 datasheet, bit 28 has no significance + * for errors M4Err-M12Err and M17Err-M21Err, on FERR_NF_FBD + */ + channel = branch & 2; + bank = NREC_BANK(info->nrecmema); rank = NREC_RANK(info->nrecmema); rdwr = NREC_RDWR(info->nrecmema); -- cgit v1.2.3-70-g09d2 From d817cd525589765aa5f6798734e422c867685a58 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Fri, 15 Jan 2010 17:01:26 -0800 Subject: virtio: fix section mismatch warnings Fix fixes the following warnings by renaming the driver structures to be suffixed with _driver. WARNING: drivers/virtio/virtio_balloon.o(.data+0x88): Section mismatch in reference from the variable virtio_balloon to the function .devexit.text:virtballoon_remove() WARNING: drivers/char/hw_random/virtio-rng.o(.data+0x88): Section mismatch in reference from the variable virtio_rng to the function .devexit.text:virtrng_remove() Signed-off-by: Jeff Mahoney Acked-by: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/hw_random/virtio-rng.c | 6 +++--- drivers/virtio/virtio_balloon.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index bdaef8e9402..64fe0a793ef 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -114,7 +114,7 @@ static struct virtio_device_id id_table[] = { { 0 }, }; -static struct virtio_driver virtio_rng = { +static struct virtio_driver virtio_rng_driver = { .driver.name = KBUILD_MODNAME, .driver.owner = THIS_MODULE, .id_table = id_table, @@ -124,12 +124,12 @@ static struct virtio_driver virtio_rng = { static int __init init(void) { - return register_virtio_driver(&virtio_rng); + return register_virtio_driver(&virtio_rng_driver); } static void __exit fini(void) { - unregister_virtio_driver(&virtio_rng); + unregister_virtio_driver(&virtio_rng_driver); } module_init(init); module_exit(fini); diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 9dd58804288..505be88c82a 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -266,7 +266,7 @@ static void __devexit virtballoon_remove(struct virtio_device *vdev) static unsigned int features[] = { VIRTIO_BALLOON_F_MUST_TELL_HOST }; -static struct virtio_driver virtio_balloon = { +static struct virtio_driver virtio_balloon_driver = { .feature_table = features, .feature_table_size = ARRAY_SIZE(features), .driver.name = KBUILD_MODNAME, @@ -279,12 +279,12 @@ static struct virtio_driver virtio_balloon = { static int __init init(void) { - return register_virtio_driver(&virtio_balloon); + return register_virtio_driver(&virtio_balloon_driver); } static void __exit fini(void) { - unregister_virtio_driver(&virtio_balloon); + unregister_virtio_driver(&virtio_balloon_driver); } module_init(init); module_exit(fini); -- cgit v1.2.3-70-g09d2 From ba168fc37dea145deeb8fa9e7e71c748d2e00d74 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 15 Jan 2010 17:01:31 -0800 Subject: memory-hotplug: add 0x prefix to HEX block_size_bytes Signed-off-by: Wu Fengguang Cc: Andi Kleen Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/memory.c b/drivers/base/memory.c index d7d77d4a402..bd025059711 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -311,7 +311,7 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); static ssize_t print_block_size(struct class *class, char *buf) { - return sprintf(buf, "%lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); + return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); } static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); -- cgit v1.2.3-70-g09d2 From 8ff410daa009c4b44be445ded5b0cec00abc0426 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 15 Jan 2010 17:01:32 -0800 Subject: sysdev: fix prototype for memory_sysdev_class show/store functions The function prototype mismatches in call stack: [] print_block_size+0x58/0x60 [] sysdev_class_show+0x1f/0x30 [] sysfs_read_file+0xcb/0x1f0 [] vfs_read+0xc8/0x180 Due to prototype mismatch, print_block_size() will sprintf() into *attribute instead of *buf, hence user space will read the initial zeros from *buf: $ hexdump /sys/devices/system/memory/block_size_bytes 0000000 0000 0000 0000 0000 0000008 After patch: cat /sys/devices/system/memory/block_size_bytes 0x8000000 This complements commits c29af9636 and 4a0b2b4dbe. Signed-off-by: Wu Fengguang Cc: Andi Kleen Cc: Greg Kroah-Hartman Cc: "Zheng, Shaohui" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/memory.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/base/memory.c b/drivers/base/memory.c index bd025059711..ae6b6c43cff 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -309,17 +309,19 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); * Block size attribute stuff */ static ssize_t -print_block_size(struct class *class, char *buf) +print_block_size(struct sysdev_class *class, + struct sysdev_class_attribute *class_attr, + char *buf) { return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); } -static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); +static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); static int block_size_init(void) { return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_block_size_bytes.attr); + &attr_block_size_bytes.attr); } /* @@ -330,7 +332,9 @@ static int block_size_init(void) */ #ifdef CONFIG_ARCH_MEMORY_PROBE static ssize_t -memory_probe_store(struct class *class, const char *buf, size_t count) +memory_probe_store(struct sysdev_class *class, + struct sysdev_class_attribute *class_attr, + const char *buf, size_t count) { u64 phys_addr; int nid; @@ -346,12 +350,12 @@ memory_probe_store(struct class *class, const char *buf, size_t count) return count; } -static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); +static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); static int memory_probe_init(void) { return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_probe.attr); + &attr_probe.attr); } #else static inline int memory_probe_init(void) @@ -367,7 +371,9 @@ static inline int memory_probe_init(void) /* Soft offline a page */ static ssize_t -store_soft_offline_page(struct class *class, const char *buf, size_t count) +store_soft_offline_page(struct sysdev_class *class, + struct sysdev_class_attribute *class_attr, + const char *buf, size_t count) { int ret; u64 pfn; @@ -384,7 +390,9 @@ store_soft_offline_page(struct class *class, const char *buf, size_t count) /* Forcibly offline a page, including killing processes. */ static ssize_t -store_hard_offline_page(struct class *class, const char *buf, size_t count) +store_hard_offline_page(struct sysdev_class *class, + struct sysdev_class_attribute *class_attr, + const char *buf, size_t count) { int ret; u64 pfn; @@ -397,18 +405,18 @@ store_hard_offline_page(struct class *class, const char *buf, size_t count) return ret ? ret : count; } -static CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); -static CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page); +static SYSDEV_CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); +static SYSDEV_CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page); static __init int memory_fail_init(void) { int err; err = sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_soft_offline_page.attr); + &attr_soft_offline_page.attr); if (!err) err = sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_hard_offline_page.attr); + &attr_hard_offline_page.attr); return err; } #else -- cgit v1.2.3-70-g09d2 From eb29a5cc0b601c458bae9df2f6c3696d75c2d383 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 15 Jan 2010 17:01:40 -0800 Subject: revert "drivers/video/s3c-fb.c: fix clock setting for Samsung SoC Framebuffer" Fix divide by zero and broken output. Commit 600ce1a0fa ("fix clock setting for Samsung SoC Framebuffer") introduced a mandatory refresh parameter to the platform data for the S3C framebuffer but did not introduce any validation code, causing existing platforms (none of which have refresh set) to divide by zero whenever the framebuffer is configured, generating warnings and unusable output. Ben Dooks noted several problems with the patch: - The platform data supplies the pixclk directly and should already have taken care of the refresh rate. - The addition of a window ID parameter doesn't help since only the root framebuffer can control the pixclk. - pixclk is specified in picoseconds (rather than Hz) as the patch assumed. and suggests reverting the commit so do that. Without fixing this no mainline user of the driver will produce output. [akpm@linux-foundation.org: don't revert the correct bit] Signed-off-by: Mark Brown Cc: InKi Dae Cc: Kyungmin Park Cc: Krzysztof Helt Cc: Marek Szyprowski Cc: Ben Dooks Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/s3c-fb.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index adf9632c6b1..53cb722c45a 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -211,21 +211,23 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, /** * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. - * @id: window id. * @sfb: The hardware state. * @pixclock: The pixel clock wanted, in picoseconds. * * Given the specified pixel clock, work out the necessary divider to get * close to the output frequency. */ -static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk) +static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) { - struct s3c_fb_pd_win *win = sfb->pdata->win[id]; unsigned long clk = clk_get_rate(sfb->bus_clk); + unsigned long long tmp; unsigned int result; - pixclk *= win->win_mode.refresh; - result = clk / pixclk; + tmp = (unsigned long long)clk; + tmp *= pixclk; + + do_div(tmp, 1000000000UL); + result = (unsigned int)tmp / 1000; dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", pixclk, clk, result, clk / result); @@ -301,7 +303,7 @@ static int s3c_fb_set_par(struct fb_info *info) /* use window 0 as the basis for the lcd output timings */ if (win_no == 0) { - clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock); + clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); data = sfb->pdata->vidcon0; data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); -- cgit v1.2.3-70-g09d2 From c14973f93027500301fc40333e16ae49e58923a7 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 10 Jan 2010 00:15:44 -0800 Subject: sony-laptop - fix using of uninitialized variable CC [M] drivers/platform/x86/sony-laptop.o drivers/platform/x86/sony-laptop.c: In function 'sony_nc_rfkill_setup': drivers/platform/x86/sony-laptop.c:1162: warning: 'i' may be used uninitialized in this function Signed-off-by: Dmitry Torokhov Acked-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5af53340da6..3f71a605a49 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1201,9 +1201,12 @@ static void sony_nc_rfkill_setup(struct acpi_device *device) /* the buffer is filled with magic numbers describing the devices * available, 0xff terminates the enumeration */ - while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff && - i < device_enum->buffer.length) { - i++; + for (i = 0; i < device_enum->buffer.length; i++) { + + dev_code = *(device_enum->buffer.pointer + i); + if (dev_code == 0xff) + break; + dprintk("Radio devices, looking at 0x%.2x\n", dev_code); if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) -- cgit v1.2.3-70-g09d2 From c97adf9e7bebf17a86b95e2131bf9ba76c4857c7 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sun, 10 Jan 2010 17:15:36 +0100 Subject: acpi: make ACPI device id constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ids field of the struct acpi_driver is constant in so it is worth to make the initialization data also constant. The semantic match that finds this kind of pattern is as follows: (http://coccinelle.lip6.fr/) // @r@ disable decl_init,const_decl_init; identifier I1, I2, x; @@ struct I1 { ... const struct I2 *x; ... }; @s@ identifier r.I1, y; identifier r.x, E; @@ struct I1 y = { .x = E, }; @c@ identifier r.I2; identifier s.E; @@ const struct I2 E[] = ... ; @depends on !c@ identifier r.I2; identifier s.E; @@ + const struct I2 E[] = ...; // Signed-off-by: Márton Németh Cc: Julia Lawall Cc: cocci@diku.dk Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 2 +- drivers/acpi/pci_root.c | 2 +- drivers/acpi/power.c | 2 +- drivers/acpi/power_meter.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 394ae89409c..04b0f007c9b 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -56,7 +56,7 @@ ACPI_MODULE_NAME("pci_link"); static int acpi_pci_link_add(struct acpi_device *device); static int acpi_pci_link_remove(struct acpi_device *device, int type); -static struct acpi_device_id link_device_ids[] = { +static const struct acpi_device_id link_device_ids[] = { {"PNP0C0F", 0}, {"", 0}, }; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 101cce3681d..64f55b6db73 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -46,7 +46,7 @@ static int acpi_pci_root_add(struct acpi_device *device); static int acpi_pci_root_remove(struct acpi_device *device, int type); static int acpi_pci_root_start(struct acpi_device *device); -static struct acpi_device_id root_device_ids[] = { +static const struct acpi_device_id root_device_ids[] = { {"PNP0A03", 0}, {"", 0}, }; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 22b29791651..0f30c3c1eea 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -65,7 +65,7 @@ static int acpi_power_remove(struct acpi_device *device, int type); static int acpi_power_resume(struct acpi_device *device); static int acpi_power_open_fs(struct inode *inode, struct file *file); -static struct acpi_device_id power_device_ids[] = { +static const struct acpi_device_id power_device_ids[] = { {ACPI_POWER_HID, 0}, {"", 0}, }; diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index 2ef7030a0c2..ca75c36f754 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c @@ -64,7 +64,7 @@ static int can_cap_in_hardware(void) return force_cap_on || cap_in_hardware; } -static struct acpi_device_id power_meter_ids[] = { +static const struct acpi_device_id power_meter_ids[] = { {"ACPI000D", 0}, {"", 0}, }; -- cgit v1.2.3-70-g09d2 From c19bdb6126a5e1f43b4a4fc3c4b09c926667e5ef Mon Sep 17 00:00:00 2001 From: Rakib Mullick Date: Sun, 3 Jan 2010 19:27:56 +0600 Subject: ACPI: Fix unused variable warning in sbs.c When CONFIG_ACPI_SYSFS_POWER=n and CONFIG_ACPI_PROCFS_POWER=n, then we're warned by the following warning: drivers/acpi/sbs.c: In function `acpi_battery_remove': drivers/acpi/sbs.c:825: warning: unused variable `battery' Signed-off-by: Rakib Mullick Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/sbs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 52b9db8afc2..b16ddbf23a9 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -822,7 +822,10 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { +#if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER) struct acpi_battery *battery = &sbs->battery[id]; +#endif + #ifdef CONFIG_ACPI_SYSFS_POWER if (battery->bat.dev) { if (battery->have_sysfs_alarm) -- cgit v1.2.3-70-g09d2 From 8c32aa5945cb05bb2ff8a91485d4477fbe55cf00 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 14 Dec 2009 14:57:49 -0300 Subject: V4L/DVB (13816): gspca - main: Set the current frame pointer when first qbuf. When not set, some images could be lost. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index e930a67d526..bd6214d4ab3 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1815,6 +1815,8 @@ static int vidioc_qbuf(struct file *file, void *priv, /* put the buffer in the 'queued' queue */ i = gspca_dev->fr_q; gspca_dev->fr_queue[i] = index; + if (gspca_dev->fr_i == i) + gspca_dev->cur_frame = frame; gspca_dev->fr_q = (i + 1) % gspca_dev->nframes; PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d", gspca_dev->fr_q, -- cgit v1.2.3-70-g09d2 From 1faea56087dfaf84019557f2c9ad18bd67c6012a Mon Sep 17 00:00:00 2001 From: Nemeth Marton Date: Tue, 15 Dec 2009 19:28:35 -0300 Subject: V4L/DVB (13820): lgdt3305: make one-bit bitfields unsigned Make one-bit bitfields unsigned which will remove the following sparse warning messages (see "make C=1"): * lgdt3305.h:57:21: error: dubious one-bit signed bitfield * lgdt3305.h:60:26: error: dubious one-bit signed bitfield * lgdt3305.h:63:19: error: dubious one-bit signed bitfield Signed-off-by: Nemeth Marton Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lgdt3305.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/lgdt3305.h b/drivers/media/dvb/frontends/lgdt3305.h index 4fa6e52d1fe..9cb11c9cae5 100644 --- a/drivers/media/dvb/frontends/lgdt3305.h +++ b/drivers/media/dvb/frontends/lgdt3305.h @@ -54,13 +54,13 @@ struct lgdt3305_config { u16 usref_qam256; /* default: 0x2a80 */ /* disable i2c repeater - 0:repeater enabled 1:repeater disabled */ - int deny_i2c_rptr:1; + unsigned int deny_i2c_rptr:1; /* spectral inversion - 0:disabled 1:enabled */ - int spectral_inversion:1; + unsigned int spectral_inversion:1; /* use RF AGC loop - 0:disabled 1:enabled */ - int rf_agc_loop:1; + unsigned int rf_agc_loop:1; enum lgdt3305_mpeg_mode mpeg_mode; enum lgdt3305_tp_clock_edge tpclk_edge; -- cgit v1.2.3-70-g09d2 From 385097e08b9c24655626ed760bc67eb7e50115a0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 22:31:21 -0300 Subject: V4L/DVB (13826): uvcvideo: Fix controls blacklisting The control blacklisting code erroneously used usb_match_id() by passing a pointer to a usb_device_id structure instead of an array of such structures. Replace the usb_match_id() call by usb_match_id_one(). Thanks to Paulo Assis for diagnosing the bug and providing an initial fix. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 0469d7a876a..ec8ef8c5560 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -1393,7 +1393,7 @@ uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity) size = entity->processing.bControlSize; for (i = 0; i < ARRAY_SIZE(blacklist); ++i) { - if (!usb_match_id(dev->intf, &blacklist[i].id)) + if (!usb_match_one_id(dev->intf, &blacklist[i].id)) continue; if (blacklist[i].index >= 8 * size || -- cgit v1.2.3-70-g09d2 From 2c4d9de8ab1434336248bbc01ee8e64d7e6b8a4f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 10 Dec 2009 21:19:31 -0300 Subject: V4L/DVB (13829): uvcvideo: Fix alternate setting selection in isochronous mode Unlike assumed by the driver, alternate settings are not sorted by endpoint max packet size. Iterate over all alternate settings to find the one with the smallest compatible max packet size. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 9a9802830d4..e8cc0a9ddad 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -924,10 +924,8 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream, static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) { struct usb_interface *intf = stream->intf; - struct usb_host_interface *alts; - struct usb_host_endpoint *ep = NULL; - int intfnum = stream->intfnum; - unsigned int bandwidth, psize, i; + struct usb_host_endpoint *ep; + unsigned int i; int ret; stream->last_fid = -1; @@ -936,6 +934,12 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) stream->bulk.payload_size = 0; if (intf->num_altsetting > 1) { + struct usb_host_endpoint *best_ep = NULL; + unsigned int best_psize = 3 * 1024; + unsigned int bandwidth; + unsigned int uninitialized_var(altsetting); + int intfnum = stream->intfnum; + /* Isochronous endpoint, select the alternate setting. */ bandwidth = stream->ctrl.dwMaxPayloadTransferSize; @@ -949,6 +953,9 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) } for (i = 0; i < intf->num_altsetting; ++i) { + struct usb_host_interface *alts; + unsigned int psize; + alts = &intf->altsetting[i]; ep = uvc_find_endpoint(alts, stream->header.bEndpointAddress); @@ -958,21 +965,27 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) /* Check if the bandwidth is high enough. */ psize = le16_to_cpu(ep->desc.wMaxPacketSize); psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - if (psize >= bandwidth) - break; + if (psize >= bandwidth && psize <= best_psize) { + altsetting = i; + best_psize = psize; + best_ep = ep; + } } - if (i >= intf->num_altsetting) { + if (best_ep == NULL) { uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting " "for requested bandwidth.\n"); return -EIO; } - ret = usb_set_interface(stream->dev->udev, intfnum, i); + uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u " + "(%u B/frame bandwidth).\n", altsetting, best_psize); + + ret = usb_set_interface(stream->dev->udev, intfnum, altsetting); if (ret < 0) return ret; - ret = uvc_init_video_isoc(stream, ep, gfp_flags); + ret = uvc_init_video_isoc(stream, best_ep, gfp_flags); } else { /* Bulk endpoint, proceed to URB initialization. */ ep = uvc_find_endpoint(&intf->altsetting[0], -- cgit v1.2.3-70-g09d2 From d7c0d43997cf716617d724554d19b3b8dd465833 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 16 Dec 2009 21:20:45 -0300 Subject: V4L/DVB (13831): uvcvideo: Fix oops caused by a race condition in buffer dequeuing Buffers were marked as done before being removed from the IRQ queue. If a userspace application dequeued and requeued the buffer fast enough during that time window, the buffer could end up being deleted twice, generating an oops in interrupt context. Add a new state, UVC_BUF_STATE_READY, to mark buffers as ready for reuse but not yet removed from the queue, and transition to UVC_BUF_STATE_DONE only when the buffer is removed from the queue. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_queue.c | 13 +++++++++---- drivers/media/video/uvc/uvc_video.c | 14 ++++++-------- drivers/media/video/uvc/uvcvideo.h | 5 +++-- 3 files changed, 18 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index f854698c406..ea11839cba4 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -59,9 +59,9 @@ * returns immediately. * * When the buffer is full, the completion handler removes it from the irq - * queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue. + * queue, marks it as done (UVC_BUF_STATE_DONE) and wakes its wait queue. * At that point, any process waiting on the buffer will be woken up. If a - * process tries to dequeue a buffer after it has been marked ready, the + * process tries to dequeue a buffer after it has been marked done, the * dequeing will succeed immediately. * * 2. Buffers are queued, user is waiting on a buffer and the device gets @@ -201,6 +201,7 @@ static void __uvc_query_buffer(struct uvc_buffer *buf, break; case UVC_BUF_STATE_QUEUED: case UVC_BUF_STATE_ACTIVE: + case UVC_BUF_STATE_READY: v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; break; case UVC_BUF_STATE_IDLE: @@ -295,13 +296,15 @@ static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) { if (nonblocking) { return (buf->state != UVC_BUF_STATE_QUEUED && - buf->state != UVC_BUF_STATE_ACTIVE) + buf->state != UVC_BUF_STATE_ACTIVE && + buf->state != UVC_BUF_STATE_READY) ? 0 : -EAGAIN; } return wait_event_interruptible(buf->wait, buf->state != UVC_BUF_STATE_QUEUED && - buf->state != UVC_BUF_STATE_ACTIVE); + buf->state != UVC_BUF_STATE_ACTIVE && + buf->state != UVC_BUF_STATE_READY); } /* @@ -348,6 +351,7 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue, case UVC_BUF_STATE_IDLE: case UVC_BUF_STATE_QUEUED: case UVC_BUF_STATE_ACTIVE: + case UVC_BUF_STATE_READY: default: uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u " "(driver bug?).\n", buf->state); @@ -489,6 +493,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, spin_lock_irqsave(&queue->irqlock, flags); list_del(&buf->queue); + buf->state = UVC_BUF_STATE_DONE; if (!list_empty(&queue->irqqueue)) nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, queue); diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index e8cc0a9ddad..7dcf534a0cf 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -441,7 +441,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, if (fid != stream->last_fid && buf->buf.bytesused != 0) { uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " "toggled).\n"); - buf->state = UVC_BUF_STATE_DONE; + buf->state = UVC_BUF_STATE_READY; return -EAGAIN; } @@ -470,7 +470,7 @@ static void uvc_video_decode_data(struct uvc_streaming *stream, /* Complete the current frame if the buffer size was exceeded. */ if (len > maxlen) { uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); - buf->state = UVC_BUF_STATE_DONE; + buf->state = UVC_BUF_STATE_READY; } } @@ -482,7 +482,7 @@ static void uvc_video_decode_end(struct uvc_streaming *stream, uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); if (data[0] == len) uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); - buf->state = UVC_BUF_STATE_DONE; + buf->state = UVC_BUF_STATE_READY; if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) stream->last_fid ^= UVC_STREAM_FID; } @@ -568,8 +568,7 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream, uvc_video_decode_end(stream, buf, mem, urb->iso_frame_desc[i].actual_length); - if (buf->state == UVC_BUF_STATE_DONE || - buf->state == UVC_BUF_STATE_ERROR) + if (buf->state == UVC_BUF_STATE_READY) buf = uvc_queue_next_buffer(&stream->queue, buf); } } @@ -627,8 +626,7 @@ static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream, if (!stream->bulk.skip_payload && buf != NULL) { uvc_video_decode_end(stream, buf, stream->bulk.header, stream->bulk.payload_size); - if (buf->state == UVC_BUF_STATE_DONE || - buf->state == UVC_BUF_STATE_ERROR) + if (buf->state == UVC_BUF_STATE_READY) buf = uvc_queue_next_buffer(&stream->queue, buf); } @@ -669,7 +667,7 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream, stream->bulk.payload_size == stream->bulk.max_payload_size) { if (buf->buf.bytesused == stream->queue.buf_used) { stream->queue.buf_used = 0; - buf->state = UVC_BUF_STATE_DONE; + buf->state = UVC_BUF_STATE_READY; uvc_queue_next_buffer(&stream->queue, buf); stream->last_fid ^= UVC_STREAM_FID; } diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 7ec9a04ced5..2337585001e 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -365,8 +365,9 @@ enum uvc_buffer_state { UVC_BUF_STATE_IDLE = 0, UVC_BUF_STATE_QUEUED = 1, UVC_BUF_STATE_ACTIVE = 2, - UVC_BUF_STATE_DONE = 3, - UVC_BUF_STATE_ERROR = 4, + UVC_BUF_STATE_READY = 3, + UVC_BUF_STATE_DONE = 4, + UVC_BUF_STATE_ERROR = 5, }; struct uvc_buffer { -- cgit v1.2.3-70-g09d2 From 9afc8022b4e7e4e8c572b2b997846756afb5d909 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 18 Dec 2009 07:47:44 -0300 Subject: V4L/DVB (13834): dib8000: fix compilation if !DVB_DIB8000 As reported by Randy Dunlap : > drivers/media/dvb/frontends/dib8000.h:104: error: expected expression before '}' token > drivers/media/dvb/frontends/dib8000.h:104: warning: left-hand operand of comma expression has no effect > > return CT_SHUTDOWN, > > s/,/;/ and fix indentation. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib8000.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h index d99619ae983..b1ee2079963 100644 --- a/drivers/media/dvb/frontends/dib8000.h +++ b/drivers/media/dvb/frontends/dib8000.h @@ -100,7 +100,7 @@ static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_ static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return CT_SHUTDOWN, + return CT_SHUTDOWN; } static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe) { -- cgit v1.2.3-70-g09d2 From bc41797a56e7995dd5f5502dd737b1e53c8e0410 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 10 Dec 2009 13:21:59 -0300 Subject: V4L/DVB (13622): gspca - ov534: Fix a compilation warning. This warning prevented the sharpness setting to work with the ov965x sensor. Reported-by: Andrew Morton Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 4dbb882c83d..0a6b8f07a69 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -1533,7 +1533,7 @@ static void setexposure_96(struct gspca_dev *gspca_dev) static void setsharpness_96(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - u8 val; + s8 val; val = sd->sharpness; if (val < 0) { /* auto */ -- cgit v1.2.3-70-g09d2 From 882ead325b167cdab89f58f871dabf9de5ac87a4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 29 Dec 2009 10:37:38 -0300 Subject: V4L/DVB (13858): ir-keytable: use the right header We don't need linux/usb/input.h but, instead, linux/input.h Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index bff7a535603..b521ed9d6e2 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -13,7 +13,7 @@ */ -#include +#include #include #define IR_TAB_MIN_SIZE 32 -- cgit v1.2.3-70-g09d2 From c60503c1db76bd46577cc7ff4fafa033b675e0e5 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 18 Dec 2009 12:22:43 -0300 Subject: V4L/DVB (13868): gspca - sn9c20x: Fix test of unsigned. Signed-off-by: Roel Kluin Signed-off-by: Jean-Francois Moine CC: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 4cff8035614..0ca1c06652b 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -2319,7 +2319,7 @@ static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) } } if (avg_lum > MAX_AVG_LUM) { - if (sd->gain - 1 >= 0) { + if (sd->gain >= 1) { sd->gain--; set_gain(gspca_dev); } -- cgit v1.2.3-70-g09d2 From 9501843496aaf85fe1767b534c4720622c4425c4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 26 Dec 2009 08:41:17 -0300 Subject: V4L/DVB (13875): gspca - vc032x: Fix a possible crash with the vc0321 bridge. The frame pointer returned by get_i_frame may be NULL when the application is too slow. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index c090efcd804..71921c87842 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -3009,6 +3009,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, int l; frame = gspca_get_i_frame(gspca_dev); + if (frame == NULL) { + gspca_dev->last_packet_type = DISCARD_PACKET; + return; + } l = frame->data_end - frame->data; if (len > frame->v4l2_buf.length - l) len = frame->v4l2_buf.length - l; -- cgit v1.2.3-70-g09d2 From 5cc60d61432f30b2d0777a15d050f6c0613887f5 Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Wed, 11 Nov 2009 07:45:37 -0300 Subject: V4L/DVB (13880): gspca - m5602-s5k4aa: Add vflip quirk for the Amilo Xi 2428 Add a vflip quirk for the Fujitsu-Siemens Amilo Xi 2428. Thanks to Myroslav Zapukhlyak for reporting. Signed-off-by: Erik Andren Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index aa2f3c7e2cb..1b536f7d30c 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -47,6 +47,12 @@ static DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528") } + }, { + .ident = "Fujitsu-Siemens Amilo Xi 2428", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428") + } }, { .ident = "Fujitsu-Siemens Amilo Xi 2528", .matches = { -- cgit v1.2.3-70-g09d2 From bbe8c8363da7251b41ee9cdb70059f04fd1bee9b Mon Sep 17 00:00:00 2001 From: Erik Andrén Date: Sat, 26 Dec 2009 18:57:21 -0300 Subject: V4L/DVB (13882): gspca - stv06xx-vv6410: Ensure register STV_SCAN_RATE is zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Quickcam Web camera would not produce an image if you removed and inserted the module multiple times without physically power cycling the camera first. By writing zero to bridge register STV_SCAN_RATE (0x1443) the camera works as intended, regardless of the number of module insertions. Signed-off-by: Erik Andrén Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h index 487d4055534..96c61926d37 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h @@ -228,6 +228,7 @@ static const struct stv_init stv_bridge_init[] = { /* This reg is written twice. Some kind of reset? */ {NULL, 0x1620, 0x80}, {NULL, 0x1620, 0x00}, + {NULL, 0x1443, 0x00}, {NULL, 0x1423, 0x04}, {x1500, 0x1500, ARRAY_SIZE(x1500)}, {x1536, 0x1536, ARRAY_SIZE(x1536)}, -- cgit v1.2.3-70-g09d2 From 19f8a6c37eead7e93660813c8873ab3e387ccb63 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 31 Dec 2009 04:32:29 -0300 Subject: V4L/DVB (13887): tda8290: add autodetection support for TDA8295c2 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda8290.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index c190b0dedee..19010f3d450 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c @@ -672,16 +672,19 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props) static int tda8295_probe(struct tuner_i2c_props *i2c_props) { #define TDA8295_ID 0x8a +#define TDA8295C2_ID 0x8b unsigned char tda8295_id[] = { 0x2f, 0x00 }; /* detect tda8295 */ tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1); tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1); - if (tda8295_id[1] == TDA8295_ID) { + if ((tda8295_id[1] & 0xfe) == TDA8295_ID) { if (debug) - printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n", - __func__, i2c_adapter_id(i2c_props->adap), + printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n", + __func__, (tda8295_id[1] == TDA8295_ID) ? + "tda8295c1" : "tda8295c2", + i2c_adapter_id(i2c_props->adap), i2c_props->addr); return 0; } -- cgit v1.2.3-70-g09d2 From 07d1c69b2dcfdd1b21e36af0ff8b9506234908ee Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 10 Jan 2010 04:32:11 -0300 Subject: V4L/DVB (13900): gspca - sunplus: Fix bridge exchanges. A previous code optimization inverted bridge registers and values, doing a regression in kernel 2.6.32. Signed-off-by: Jean-Francois Moine CC: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sunplus.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 716df6b15fc..306b7d75b4a 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -709,7 +709,7 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) spca504B_PollingDataReady(gspca_dev); /* Init the cam width height with some values get on init ? */ - reg_w_riv(gspca_dev, 0x31, 0, 0x04); + reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); spca504B_WaitCmdStatus(gspca_dev); spca504B_PollingDataReady(gspca_dev); break; @@ -807,14 +807,14 @@ static void init_ctl_reg(struct gspca_dev *gspca_dev) default: /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA504B: */ - reg_w_riv(gspca_dev, 0, 0x00, 0x21ad); /* hue */ - reg_w_riv(gspca_dev, 0, 0x01, 0x21ac); /* sat/hue */ - reg_w_riv(gspca_dev, 0, 0x00, 0x21a3); /* gamma */ + reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */ + reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */ + reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */ break; case BRIDGE_SPCA536: - reg_w_riv(gspca_dev, 0, 0x40, 0x20f5); - reg_w_riv(gspca_dev, 0, 0x01, 0x20f4); - reg_w_riv(gspca_dev, 0, 0x00, 0x2089); + reg_w_riv(gspca_dev, 0, 0x20f5, 0x40); + reg_w_riv(gspca_dev, 0, 0x20f4, 0x01); + reg_w_riv(gspca_dev, 0, 0x2089, 0x00); break; } if (pollreg) @@ -887,11 +887,11 @@ static int sd_init(struct gspca_dev *gspca_dev) switch (sd->bridge) { case BRIDGE_SPCA504B: reg_w_riv(gspca_dev, 0x1d, 0x00, 0); - reg_w_riv(gspca_dev, 0, 0x01, 0x2306); - reg_w_riv(gspca_dev, 0, 0x00, 0x0d04); - reg_w_riv(gspca_dev, 0, 0x00, 0x2000); - reg_w_riv(gspca_dev, 0, 0x13, 0x2301); - reg_w_riv(gspca_dev, 0, 0x00, 0x2306); + reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01); + reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00); + reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00); + reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13); + reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00); /* fall thru */ case BRIDGE_SPCA533: spca504B_PollingDataReady(gspca_dev); @@ -1000,7 +1000,7 @@ static int sd_start(struct gspca_dev *gspca_dev) spca504B_WaitCmdStatus(gspca_dev); break; default: - reg_w_riv(gspca_dev, 0x31, 0, 0x04); + reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); spca504B_WaitCmdStatus(gspca_dev); spca504B_PollingDataReady(gspca_dev); break; -- cgit v1.2.3-70-g09d2 From 3f76cf8c8ed10da1ce50f821366d0dc590397069 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 10 Jan 2010 18:13:33 -0300 Subject: V4L/DVB (13934): tda8290: Fix FM radio easy programming standard selection for TDA8295 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda8290.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index 19010f3d450..2833137fa81 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c @@ -144,7 +144,8 @@ static void set_audio(struct dvb_frontend *fe, } if (params->mode == V4L2_TUNER_RADIO) { - priv->tda8290_easy_mode = 0x01; /* Start with MN values */ + /* Set TDA8295 to FM radio; Start TDA8290 with MN values */ + priv->tda8290_easy_mode = (priv->ver & TDA8295) ? 0x80 : 0x01; tuner_dbg("setting to radio FM\n"); } else { tuner_dbg("setting tda829x to system %s\n", mode); -- cgit v1.2.3-70-g09d2 From 30883ea8f2b489ccbb6aa0755832218ec45468a1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 9 Jan 2010 20:44:06 -0300 Subject: V4L/DVB mx1_camera: don't check platform_get_irq's return value against zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit platform_get_irq returns -ENXIO on failure, so !irq was probably always true. Better use (int)irq <= 0. Note that a return value of zero is still handled as error even though this could mean irq0. This is a followup to 305b3228f9ff4d59f49e6d34a7034d44ee8ce2f0 that changed the return value of platform_get_irq from 0 to -ENXIO on error. Cc: David Vrabel Cc: Greg Kroah-Hartman Cc: Mauro Carvalho Chehab Cc: Guennadi Liakhovetski Cc: Antonio Ospite Cc: Paulius Zaleckas Cc: linux-media@vger.kernel.org Signed-off-by: Uwe Kleine-König Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mx1_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 2ba14fb5b03..c167cc3de49 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -718,7 +718,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!res || !irq) { + if (!res || (int)irq <= 0) { err = -ENODEV; goto exit; } -- cgit v1.2.3-70-g09d2 From b89fc2e5e7b6d6da3ab9a2dc05810794e5eac869 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 9 Jan 2010 20:45:13 -0300 Subject: V4L/DVB sh_mobile_ceu: don't check platform_get_irq's return value against zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit platform_get_irq returns -ENXIO on failure, so !irq was probably always true. Better use (int)irq <= 0. Note that a return value of zero is still handled as error even though this could mean irq0. This is a followup to 305b3228f9ff4d59f49e6d34a7034d44ee8ce2f0 that changed the return value of platform_get_irq from 0 to -ENXIO on error. Cc: David Vrabel Cc: Greg Kroah-Hartman Cc: Mauro Carvalho Chehab Cc: Guennadi Liakhovetski Cc: Magnus Damm Cc: Kuninori Morimoto Cc: Paul Mundt Cc: linux-media@vger.kernel.org Signed-off-by: Uwe Kleine-König Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sh_mobile_ceu_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index d69363f0d8c..f09c7140d6b 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -1827,7 +1827,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!res || !irq) { + if (!res || (int)irq <= 0) { dev_err(&pdev->dev, "Not enough CEU platform resources.\n"); err = -ENODEV; goto exit; -- cgit v1.2.3-70-g09d2 From 21c91d2ee8b547e9661892d0532f69082c8a97aa Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sat, 9 Jan 2010 20:45:59 -0300 Subject: V4L/DVB (13941): rj54n1cb0c: remove compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the following compiler warning: 'dummy' is used uninitialized in this function. Although the result in the dummy variable is not used the program flow in soc_camera_limit_side() depends on the value in dummy. The program flow is better to be deterministic. Signed-off-by: Márton Németh Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/rj54n1cb0c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 7e42989ce0e..805226e0d9c 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c @@ -563,7 +563,7 @@ static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) struct i2c_client *client = sd->priv; struct rj54n1 *rj54n1 = to_rj54n1(client); struct v4l2_rect *rect = &a->c; - unsigned int dummy, output_w, output_h, + unsigned int dummy = 0, output_w, output_h, input_w = rect->width, input_h = rect->height; int ret; -- cgit v1.2.3-70-g09d2 From 423f5c0d016cd6b65c468d3dcdeeb708ee68074b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 28 Dec 2009 13:59:46 -0300 Subject: V4L/DVB (13955): cx25821: fix double unlock in medusa_video_init() medusa_set_videostandard() takes the lock but it always drops it before returning. This was found with a static checker and compile tested only. :/ Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/cx25821/cx25821-medusa-video.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c index e4df8134f05..1eb079b3d42 100644 --- a/drivers/staging/cx25821/cx25821-medusa-video.c +++ b/drivers/staging/cx25821/cx25821-medusa-video.c @@ -860,10 +860,8 @@ int medusa_video_init(struct cx25821_dev *dev) ret_val = medusa_set_videostandard(dev); - if (ret_val < 0) { - mutex_unlock(&dev->lock); + if (ret_val < 0) return -EINVAL; - } return 1; } -- cgit v1.2.3-70-g09d2 From 08be64be3d1e5ecd72e7ba3147aea518e527f08e Mon Sep 17 00:00:00 2001 From: Dmitri Belimov Date: Fri, 8 Jan 2010 06:38:28 -0300 Subject: V4L/DVB (13966): DVB-T regression fix for saa7134 cards Some customers has problem with quality of DVB-T https://bugs.launchpad.net/ubuntu/+source/linux/+bug/446575 After this patch http://patchwork.kernel.org/patch/23345/ This is patch for fix regression with DVB-T. Tested with many people. Signed-off-by: Alexey Osipov Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 13 ------------- drivers/media/video/saa7134/saa7134-ts.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 9f85e917f9f..a7ad7810fdd 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -420,19 +420,6 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) ctrl |= SAA7134_MAIN_CTRL_TE5; irq |= SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0; - - /* dma: setup channel 5 (= TS) */ - - saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff); - saa_writeb(SAA7134_TS_DMA1, - ((dev->ts.nr_packets - 1) >> 8) & 0xff); - /* TSNOPIT=0, TSCOLAP=0 */ - saa_writeb(SAA7134_TS_DMA2, - (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00); - saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); - saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 | - SAA7134_RS_CONTROL_ME | - (dev->ts.pt_ts.dma >> 12)); } /* set task conditions + field handling */ diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index 03488ba4c99..b9817d74943 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -250,6 +250,19 @@ int saa7134_ts_start(struct saa7134_dev *dev) BUG_ON(dev->ts_started); + /* dma: setup channel 5 (= TS) */ + saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff); + saa_writeb(SAA7134_TS_DMA1, + ((dev->ts.nr_packets - 1) >> 8) & 0xff); + /* TSNOPIT=0, TSCOLAP=0 */ + saa_writeb(SAA7134_TS_DMA2, + (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00); + saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); + saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 | + SAA7134_RS_CONTROL_ME | + (dev->ts.pt_ts.dma >> 12)); + + /* reset hardware TS buffers */ saa_writeb(SAA7134_TS_SERIAL1, 0x00); saa_writeb(SAA7134_TS_SERIAL1, 0x03); saa_writeb(SAA7134_TS_SERIAL1, 0x00); -- cgit v1.2.3-70-g09d2 From 41e840b13e111ba18b138d055ddd250bd5ad5e39 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 21:57:10 -0300 Subject: V4L/DVB (13699): [Mantis, MB86A16] Initial checkin: Mantis, MB86A16 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 1772 ++++++++++++++++++++++++++++ drivers/media/dvb/frontends/mb86a16.h | 38 + drivers/media/dvb/frontends/mb86a16_priv.h | 151 +++ drivers/media/dvb/mantis/Kconfig | 13 + drivers/media/dvb/mantis/Makefile | 7 + drivers/media/dvb/mantis/mantis_common.h | 135 +++ drivers/media/dvb/mantis/mantis_core.c | 215 ++++ drivers/media/dvb/mantis/mantis_core.h | 61 + drivers/media/dvb/mantis/mantis_dma.c | 238 ++++ drivers/media/dvb/mantis/mantis_dvb.c | 304 +++++ drivers/media/dvb/mantis/mantis_i2c.c | 189 +++ drivers/media/dvb/mantis/mantis_reg.h | 109 ++ drivers/media/dvb/mantis/mantis_vp1033.c | 151 +++ drivers/media/dvb/mantis/mantis_vp1033.h | 35 + drivers/media/dvb/mantis/mantis_vp1034.c | 52 + drivers/media/dvb/mantis/mantis_vp1034.h | 30 + drivers/media/dvb/mantis/mantis_vp2033.c | 73 ++ drivers/media/dvb/mantis/mantis_vp2033.h | 33 + drivers/media/dvb/mantis/mantis_vp3030.c | 53 + drivers/media/dvb/mantis/mantis_vp3030.h | 30 + 20 files changed, 3689 insertions(+) create mode 100644 drivers/media/dvb/frontends/mb86a16.c create mode 100644 drivers/media/dvb/frontends/mb86a16.h create mode 100644 drivers/media/dvb/frontends/mb86a16_priv.h create mode 100644 drivers/media/dvb/mantis/Kconfig create mode 100644 drivers/media/dvb/mantis/Makefile create mode 100644 drivers/media/dvb/mantis/mantis_common.h create mode 100644 drivers/media/dvb/mantis/mantis_core.c create mode 100644 drivers/media/dvb/mantis/mantis_core.h create mode 100644 drivers/media/dvb/mantis/mantis_dma.c create mode 100644 drivers/media/dvb/mantis/mantis_dvb.c create mode 100644 drivers/media/dvb/mantis/mantis_i2c.c create mode 100644 drivers/media/dvb/mantis/mantis_reg.h create mode 100644 drivers/media/dvb/mantis/mantis_vp1033.c create mode 100644 drivers/media/dvb/mantis/mantis_vp1033.h create mode 100644 drivers/media/dvb/mantis/mantis_vp1034.c create mode 100644 drivers/media/dvb/mantis/mantis_vp1034.h create mode 100644 drivers/media/dvb/mantis/mantis_vp2033.c create mode 100644 drivers/media/dvb/mantis/mantis_vp2033.h create mode 100644 drivers/media/dvb/mantis/mantis_vp3030.c create mode 100644 drivers/media/dvb/mantis/mantis_vp3030.h (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c new file mode 100644 index 00000000000..6a78a0c7403 --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -0,0 +1,1772 @@ +/* + Fujitsu MB86A16 DVB-S/DSS DC Receiver driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "mb86a16.h" +#include "mb86a16_priv.h" + +unsigned int verbose = 5; +module_param(verbose, int, 0644); + +#define ABS(x) ((x) < 0 ? (-x) : (x)) + +struct mb86a16_state { + struct i2c_adapter *i2c_adap; + const struct mb86a16_config *config; + struct dvb_frontend frontend; + u8 signal; + + // tuning parameters + int frequency; + int srate; + + // Internal stuff + int master_clk; + int deci; + int csel; + int rsel; +}; + +#define MB86A16_ERROR 0 +#define MB86A16_NOTICE 1 +#define MB86A16_INFO 2 +#define MB86A16_DEBUG 3 + +#define dprintk(x, y, z, format, arg...) do { \ + if (z) { \ + if ((x > MB86A16_ERROR) && (x > y)) \ + printk(KERN_ERR "%s: " format "\n", __func__, ##arg); \ + else if ((x > MB86A16_NOTICE) && (x > y)) \ + printk(KERN_NOTICE "%s: " format "\n", __func__, ##arg); \ + else if ((x > MB86A16_INFO) && (x > y)) \ + printk(KERN_INFO "%s: " format "\n", __func__, ##arg); \ + else if ((x > MB86A16_DEBUG) && (x > y)) \ + printk(KERN_DEBUG "%s: " format "\n", __func__, ##arg); \ + } else { \ + if (x > y) \ + printk(format, ##arg); \ + } \ +} while (0) + +#define TRACE_IN dprintk(verbose, MB86A16_DEBUG, 1, "-->()") +#define TRACE_OUT dprintk(verbose, MB86A16_DEBUG, 1, "()-->") + +static int mb86a16_write(struct mb86a16_state *state, u8 reg, u8 val) +{ + int ret; + u8 buf[] = { reg, val }; + + struct i2c_msg msg = { + .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = 2 + }; + + dprintk(verbose, MB86A16_DEBUG, 1, + "writing to [0x%02x],Reg[0x%02x],Data[0x%02x]", + state->config->demod_address, buf[0], buf[1]); + + ret = i2c_transfer(state->i2c_adap, &msg, 1); + + return (ret != 1) ? -EREMOTEIO : 0; +} + +static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val) +{ + int ret; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + + struct i2c_msg msg[] = { + { + .addr = state->config->demod_address, + .flags = 0, + .buf = b0, + .len = 1 + },{ + .addr = state->config->demod_address, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + } + }; + ret = i2c_transfer(state->i2c_adap, msg, 2); + if (ret != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=0x%i)", + reg, ret); + + return -EREMOTEIO; + } + *val = b1[0]; + + return ret; +} + +static int CNTM_set(struct mb86a16_state *state, + unsigned char timint1, + unsigned char timint2, + unsigned char cnext) +{ + unsigned char val; + + val = (timint1 << 4) | (timint2 << 2) | cnext; + if (mb86a16_write(state, MB86A16_CNTMR, val) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int smrt_set(struct mb86a16_state *state, int rate) +{ + int tmp ; + int m ; + unsigned char STOFS0, STOFS1; + + m = 1 << state->deci; + tmp = (8192 * state->master_clk - 2 * m * rate * 8192 + state->master_clk / 2) / state->master_clk; + + STOFS0 = tmp & 0x0ff; + STOFS1 = (tmp & 0xf00) >> 8; + + if (mb86a16_write(state, MB86A16_SRATE1, (state->deci << 2) | + (state->csel << 1) | + state->rsel) < 0) + goto err; + if (mb86a16_write(state, MB86A16_SRATE2, STOFS0) < 0) + goto err; + if (mb86a16_write(state, MB86A16_SRATE3, STOFS1) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -1; +} + +static int srst(struct mb86a16_state *state) +{ + if (mb86a16_write(state, MB86A16_RESET, 0x04) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + +} + +static int afcex_data_set(struct mb86a16_state *state, + unsigned char AFCEX_L, + unsigned char AFCEX_H) +{ + if (mb86a16_write(state, MB86A16_AFCEXL, AFCEX_L) < 0) + goto err; + if (mb86a16_write(state, MB86A16_AFCEXH, AFCEX_H) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + + return -1; +} + +static int afcofs_data_set(struct mb86a16_state *state, + unsigned char AFCEX_L, + unsigned char AFCEX_H) +{ + if (mb86a16_write(state, 0x58, AFCEX_L) < 0) + goto err; + if (mb86a16_write(state, 0x59, AFCEX_H) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int stlp_set(struct mb86a16_state *state, + unsigned char STRAS, + unsigned char STRBS) +{ + if (mb86a16_write(state, MB86A16_STRFILTCOEF1, (STRBS << 3) | (STRAS)) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int Vi_set(struct mb86a16_state *state, unsigned char ETH, unsigned char VIA) +{ + if (mb86a16_write(state, MB86A16_VISET2, 0x04) < 0) + goto err; + if (mb86a16_write(state, MB86A16_VISET3, 0xf5) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int initial_set(struct mb86a16_state *state) +{ + if (stlp_set(state, 5, 7)) + goto err; + if (afcex_data_set(state, 0, 0)) + goto err; + if (afcofs_data_set(state, 0, 0)) + goto err; + + if (mb86a16_write(state, MB86A16_CRLFILTCOEF1, 0x16) < 0) + goto err; + if (mb86a16_write(state, 0x2f, 0x21) < 0) + goto err; + if (mb86a16_write(state, MB86A16_VIMAG, 0x38) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS1, 0x00) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS2, 0x1c) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS3, 0x20) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS4, 0x1e) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS5, 0x23) < 0) + goto err; + if (mb86a16_write(state, 0x54, 0xff) < 0) + goto err; + if (mb86a16_write(state, MB86A16_TSOUT, 0x00) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int S01T_set(struct mb86a16_state *state, + unsigned char s1t, + unsigned s0t) +{ + if (mb86a16_write(state, 0x33, (s1t << 3) | s0t) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + + +static int EN_set(struct mb86a16_state *state, + int cren, + int afcen) +{ + unsigned char val; + + val = 0x7a | (cren << 7) | (afcen << 2); + if (mb86a16_write(state, 0x49, val) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int AFCEXEN_set(struct mb86a16_state *state, + int afcexen, + int smrt) +{ + unsigned char AFCA ; + + if (smrt > 18875) + AFCA = 4; + else if (smrt > 9375) + AFCA = 3; + else if (smrt > 2250) + AFCA = 2; + else + AFCA = 1; + + if (mb86a16_write(state, 0x2a, 0x02 | (afcexen << 5) | (AFCA << 2)) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int DAGC_data_set(struct mb86a16_state *state, + unsigned char DAGCA, + unsigned char DAGCW) +{ + if (mb86a16_write(state, 0x2d, (DAGCA << 3) | DAGCW) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static void smrt_info_get(struct mb86a16_state *state, int rate) +{ + if (rate >= 37501) { + state->deci = 0; state->csel = 0; state->rsel = 0; + } else if (rate >= 30001) { + state->deci = 0; state->csel = 0; state->rsel = 1; + } else if (rate >= 26251) { + state->deci = 0; state->csel = 1; state->rsel = 0; + } else if (rate >= 22501) { + state->deci = 0; state->csel = 1; state->rsel = 1; + } else if (rate >= 18751) { + state->deci = 1; state->csel = 0; state->rsel = 0; + } else if (rate >= 15001) { + state->deci = 1; state->csel = 0; state->rsel = 1; + } else if (rate >= 13126) { + state->deci = 1; state->csel = 1; state->rsel = 0; + } else if (rate >= 11251) { + state->deci = 1; state->csel = 1; state->rsel = 1; + } else if (rate >= 9376) { + state->deci = 2; state->csel = 0; state->rsel = 0; + } else if (rate >= 7501) { + state->deci = 2; state->csel = 0; state->rsel = 1; + } else if (rate >= 6563) { + state->deci = 2; state->csel = 1; state->rsel = 0; + } else if (rate >= 5626) { + state->deci = 2; state->csel = 1; state->rsel = 1; + } else if (rate >= 4688) { + state->deci = 3; state->csel = 0; state->rsel = 0; + } else if (rate >= 3751) { + state->deci = 3; state->csel = 0; state->rsel = 1; + } else if (rate >= 3282) { + state->deci = 3; state->csel = 1; state->rsel = 0; + } else if (rate >= 2814) { + state->deci = 3; state->csel = 1; state->rsel = 1; + } else if (rate >= 2344) { + state->deci = 4; state->csel = 0; state->rsel = 0; + } else if (rate >= 1876) { + state->deci = 4; state->csel = 0; state->rsel = 1; + } else if (rate >= 1641) { + state->deci = 4; state->csel = 1; state->rsel = 0; + } else if (rate >= 1407) { + state->deci = 4; state->csel = 1; state->rsel = 1; + } else if (rate >= 1172) { + state->deci = 5; state->csel = 0; state->rsel = 0; + } else if (rate >= 939) { + state->deci = 5; state->csel = 0; state->rsel = 1; + } else if (rate >= 821) { + state->deci = 5; state->csel = 1; state->rsel = 0; + } else { + state->deci = 5; state->csel = 1; state->rsel = 1; + } + + if (state->csel == 0) + state->master_clk = 92000; + else + state->master_clk = 61333; + +} + +static int signal_det(struct mb86a16_state *state, + int smrt, + unsigned char *SIG) +{ + + int ret ; + int smrtd ; + int wait_sym ; + int wait_t ; + unsigned char S[3] ; + int i ; + + if (*SIG > 45) { + if (CNTM_set(state, 2, 1, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); + return -1; + } + wait_sym = 40000; + } else { + if (CNTM_set(state, 3, 1, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); + return -1; + } + wait_sym = 80000; + } + for (i = 0; i < 3; i++) { + if (i == 0 ) + smrtd = smrt * 98 / 100; + else if (i == 1) + smrtd = smrt; + else + smrtd = smrt * 102 / 100; + smrt_info_get(state, smrtd); + smrt_set(state, smrtd); + srst(state); + wait_t = (wait_sym + 99 * smrtd / 100) / smrtd; + if (wait_t == 0) + wait_t = 1; + msleep_interruptible(10); + if (mb86a16_read(state, 0x37, &(S[i])) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + } + if ((S[1] > S[0] * 112 / 100) && + (S[1] > S[2] * 112 / 100)) { + + ret = 1; + } else { + ret = 0; + } + *SIG = S[1]; + + if (CNTM_set(state, 0, 1, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); + return -1; + } + + return ret; +} + +static int rf_val_set(struct mb86a16_state *state, + int f, + int smrt, + unsigned char R) +{ + unsigned char C, F, B; + int M; + unsigned char rf_val[5]; + int ack = -1; + + if (smrt > 37750 ) + C = 1; + else if (smrt > 18875) + C = 2; + else if (smrt > 5500 ) + C = 3; + else + C = 4; + + if (smrt > 30500) + F = 3; + else if (smrt > 9375) + F = 1; + else if (smrt > 4625) + F = 0; + else + F = 2; + + if (f < 1060) + B = 0; + else if (f < 1175) + B = 1; + else if (f < 1305) + B = 2; + else if (f < 1435) + B = 3; + else if (f < 1570) + B = 4; + else if (f < 1715) + B = 5; + else if (f < 1845) + B = 6; + else if (f < 1980) + B = 7; + else if (f < 2080) + B = 8; + else + B = 9; + + M = f * (1 << R) / 2; + + rf_val[0] = 0x01 | (C << 3) | (F << 1); + rf_val[1] = (R << 5) | ((M & 0x1f000) >> 12); + rf_val[2] = (M & 0x00ff0) >> 4; + rf_val[3] = ((M & 0x0000f) << 4) | B; + + // Frequency Set + if (mb86a16_write(state, 0x21, rf_val[0]) < 0) + ack = 0; + if (mb86a16_write(state, 0x22, rf_val[1]) < 0) + ack = 0; + if (mb86a16_write(state, 0x23, rf_val[2]) < 0) + ack = 0; + if (mb86a16_write(state, 0x24, rf_val[3]) < 0) + ack = 0; + if (mb86a16_write(state, 0x25, 0x01) < 0) + ack = 0; + if (ack == 0) { + dprintk(verbose, MB86A16_ERROR, 1, "RF Setup - I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int afcerr_chk(struct mb86a16_state *state) +{ + unsigned char AFCM_L, AFCM_H ; + int AFCM ; + int afcm, afcerr ; + + if (mb86a16_read(state, 0x0e, &AFCM_L) != 2) + goto err; + if (mb86a16_read(state, 0x0f, &AFCM_H) != 2) + goto err; + + AFCM = (AFCM_H << 8) + AFCM_L; + + if (AFCM > 2048) + afcm = AFCM - 4096; + else + afcm = AFCM; + afcerr = afcm * state->master_clk / 8192; + + return afcerr; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int dagcm_val_get(struct mb86a16_state *state) +{ + int DAGCM; + unsigned char DAGCM_H, DAGCM_L; + + if (mb86a16_read(state, 0x45, &DAGCM_L) != 2) + goto err; + if (mb86a16_read(state, 0x46, &DAGCM_H) != 2) + goto err; + + DAGCM = (DAGCM_H << 8) + DAGCM_L; + + return DAGCM; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct mb86a16_state *state = fe->demodulator_priv; + + if (state->signal & 0x02) + *status |= FE_HAS_VITERBI; + if (state->signal & 0x01) + *status |= FE_HAS_SYNC; + if (state->signal & 0x03) + *status |= FE_HAS_LOCK; + + return 0; +} + +static int sync_chk(struct mb86a16_state *state, + unsigned char *VIRM) +{ + unsigned char val; + int sync; + + if (mb86a16_read(state, 0x0d, &val) != 2) + goto err; + + dprintk(verbose, MB86A16_INFO, 1, "Status = %02x,", val); + sync = val & 0x01; + *VIRM = (val & 0x1c) >> 2; + + return sync; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + +} + +static int freqerr_chk(struct mb86a16_state *state, + int fTP, + int smrt, + int unit) +{ + unsigned char CRM, AFCML, AFCMH; + unsigned char temp1, temp2, temp3; + int crm, afcm, AFCM; + int crrerr, afcerr; // [kHz] + int frqerr; // [MHz] + int afcen, afcexen = 0; + int R, M, fOSC, fOSC_OFS; + + if (mb86a16_read(state, 0x43, &CRM) != 2) + goto err; + + if (CRM > 127) + crm = CRM - 256; + else + crm = CRM; + + crrerr = smrt * crm / 256; + if (mb86a16_read(state, 0x49, &temp1) != 2) + goto err; + + afcen = (temp1 & 0x04) >> 2; + if (afcen == 0) { + if (mb86a16_read(state, 0x2a, &temp1) != 2) + goto err; + afcexen = (temp1 & 0x20) >> 5; + } + + if (afcen == 1) { + if (mb86a16_read(state, 0x0e, &AFCML) != 2) + goto err; + if (mb86a16_read(state, 0x0f, &AFCMH) != 2) + goto err; + } else if (afcexen == 1) { + if (mb86a16_read(state, 0x2b, &AFCML) != 2) + goto err; + if (mb86a16_read(state, 0x2c, &AFCMH) != 2) + goto err; + } + if ((afcen == 1) || (afcexen == 1)) { + smrt_info_get(state, smrt); + AFCM = ((AFCMH & 0x01) << 8) + AFCML; + if (AFCM > 255) + afcm = AFCM - 512; + else + afcm = AFCM; + + afcerr = afcm * state->master_clk / 8192; + } else + afcerr = 0; + + if (mb86a16_read(state, 0x22, &temp1) != 2) + goto err; + if (mb86a16_read(state, 0x23, &temp2) != 2) + goto err; + if (mb86a16_read(state, 0x24, &temp3) != 2) + goto err; + + R = (temp1 & 0xe0) >> 5; + M = ((temp1 & 0x1f) << 12) + (temp2 << 4) + (temp3 >> 4); + if (R == 0) + fOSC = 2 * M; + else + fOSC = M; + + fOSC_OFS = fOSC - fTP; + + if (unit == 0) { //[MHz] + if (crrerr + afcerr + fOSC_OFS * 1000 >= 0) + frqerr = (crrerr + afcerr + fOSC_OFS * 1000 + 500) / 1000; + else + frqerr = (crrerr + afcerr + fOSC_OFS * 1000 - 500) / 1000; + } else { //[kHz] + frqerr = crrerr + afcerr + fOSC_OFS * 1000; + } + + return frqerr; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static unsigned char vco_dev_get(struct mb86a16_state *state, int smrt) +{ + unsigned char R; + + if (smrt > 9375) + R = 0; + else + R = 1; + + return R; +} + +static void swp_info_get(struct mb86a16_state *state, + int fOSC_start, + int smrt, + int v, int R, + int swp_ofs, + int *fOSC, + int *afcex_freq, + unsigned char *AFCEX_L, + unsigned char *AFCEX_H) +{ + int AFCEX ; + int crnt_swp_freq ; + + crnt_swp_freq = fOSC_start * 1000 + v * swp_ofs; + + if (R == 0 ) + *fOSC = (crnt_swp_freq + 1000) / 2000 * 2; + else + *fOSC = (crnt_swp_freq + 500) / 1000; + + if (*fOSC >= crnt_swp_freq) + *afcex_freq = *fOSC *1000 - crnt_swp_freq; + else + *afcex_freq = crnt_swp_freq - *fOSC * 1000; + + AFCEX = *afcex_freq * 8192 / state->master_clk; + *AFCEX_L = AFCEX & 0x00ff; + *AFCEX_H = (AFCEX & 0x0f00) >> 8; +} + + +static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V, int vmax, int vmin, + int SIGMIN, int fOSC, int afcex_freq, int swp_ofs, unsigned char *SIG1) +{ + int swp_freq ; + + if ((i % 2 == 1) && (v <= vmax)) { + // positive v (case 1) + if ((v - 1 == vmin) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v - 1) >= 0) && + (*(V + 30 + v - 1) > *(V + 30 + v)) && + (*(V + 30 + v - 1) > SIGMIN)) { + + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; + *SIG1 = *(V + 30 + v - 1); + } else if ((v == vmax) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v - 1) >= 0) && + (*(V + 30 + v) > *(V + 30 + v - 1)) && + (*(V + 30 + v) > SIGMIN)) { + // (case 2) + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else if ((*(V + 30 + v) > 0) && + (*(V + 30 + v - 1) > 0) && + (*(V + 30 + v - 2) > 0) && + (*(V + 30 + v - 3) > 0) && + (*(V + 30 + v - 1) > *(V + 30 + v)) && + (*(V + 30 + v - 2) > *(V + 30 + v - 3)) && + ((*(V + 30 + v - 1) > SIGMIN) || + (*(V + 30 + v - 2) > SIGMIN))) { + // (case 3) + if (*(V + 30 + v - 1) >= *(V + 30 + v - 2)) { + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; + *SIG1 = *(V + 30 + v - 1); + } else { + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs * 2; + *SIG1 = *(V + 30 + v - 2); + } + } else if ((v == vmax) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v - 1) >= 0) && + (*(V + 30 + v - 2) >= 0) && + (*(V + 30 + v) > *(V + 30 + v - 2)) && + (*(V + 30 + v - 1) > *(V + 30 + v - 2)) && + ((*(V + 30 + v) > SIGMIN) || + (*(V + 30 + v - 1) > SIGMIN))) { + // (case 4) + if (*(V + 30 + v) >= *(V + 30 + v - 1)) { + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else { + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; + *SIG1 = *(V + 30 + v - 1); + } + } else { + swp_freq = -1 ; + } + } else if ((i % 2 == 0) && (v >= vmin)) { + // Negative v (case 1) + if ((*(V + 30 + v) > 0) && + (*(V + 30 + v + 1) > 0) && + (*(V + 30 + v + 2) > 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 1) > *(V + 30 + v + 2)) && + (*(V + 30 + v + 1) > SIGMIN)) { + + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } else if ((v + 1 == vmax) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 1) > SIGMIN)) { + // (case 2) + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v); + } else if ((v == vmin) && + (*(V + 30 + v) > 0) && + (*(V + 30 + v + 1) > 0) && + (*(V + 30 + v + 2) > 0) && + (*(V + 30 + v) > *(V + 30 + v + 1)) && + (*(V + 30 + v) > *(V + 30 + v + 2)) && + (*(V + 30 + v) > SIGMIN)) { + // (case 3) + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else if ((*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 2) >= 0) && + (*(V +30 + v + 3) >= 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 2) > *(V + 30 + v + 3)) && + ((*(V + 30 + v + 1) > SIGMIN) || + (*(V + 30 + v + 2) > SIGMIN))) { + // (case 4) + if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } else { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2; + *SIG1 = *(V + 30 + v + 2); + } + } else if ((*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 2) >= 0) && + (*(V + 30 + v + 3) >= 0) && + (*(V + 30 + v) > *(V + 30 + v + 2)) && + (*(V + 30 + v + 1) > *(V + 30 + v + 2)) && + (*(V + 30 + v) > *(V + 30 + v + 3)) && + (*(V + 30 + v + 1) > *(V + 30 + v + 3)) && + ((*(V + 30 + v) > SIGMIN) || + (*(V + 30 + v + 1) > SIGMIN))) { + // (case 5) + if (*(V + 30 + v) >= *(V + 30 + v + 1)) { + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } + } else if ((v + 2 == vmin) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 2) >= 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 2) > *(V + 30 + v)) && + ((*(V + 30 + v + 1) > SIGMIN) || + (*(V + 30 + v + 2) > SIGMIN))) { + // (case 6) + if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } else { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2; + *SIG1 = *(V + 30 + v + 2); + } + } else if ((vmax == 0) && (vmin == 0) && (*(V + 30 + v) > SIGMIN)) { + swp_freq = fOSC * 1000; + *SIG1 = *(V + 30 + v); + } else swp_freq = -1; + } else swp_freq = -1; + + return swp_freq; +} + +static void swp_info_get2(struct mb86a16_state *state, + int smrt, + int R, + int swp_freq, + int *afcex_freq, + int *fOSC, + unsigned char *AFCEX_L, + unsigned char *AFCEX_H) +{ + int AFCEX ; + + if (R == 0) + *fOSC = (swp_freq + 1000) / 2000 * 2; + else + *fOSC = (swp_freq + 500) / 1000; + + if (*fOSC >= swp_freq) + *afcex_freq = *fOSC * 1000 - swp_freq; + else + *afcex_freq = swp_freq - *fOSC * 1000; + + AFCEX = *afcex_freq * 8192 / state->master_clk; + *AFCEX_L = AFCEX & 0x00ff; + *AFCEX_H = (AFCEX & 0x0f00) >> 8; +} + +static void afcex_info_get(struct mb86a16_state *state, + int afcex_freq, + unsigned char *AFCEX_L, + unsigned char *AFCEX_H) +{ + int AFCEX ; + + AFCEX = afcex_freq * 8192 / state->master_clk; + *AFCEX_L = AFCEX & 0x00ff; + *AFCEX_H = (AFCEX & 0x0f00) >> 8; +} + +static int SEQ_set(struct mb86a16_state *state, unsigned char loop) +{ + // SLOCK0 = 0 + if (mb86a16_write(state, 0x32, 0x02 | (loop << 2)) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int iq_vt_set(struct mb86a16_state *state, unsigned char IQINV) +{ + // Viterbi Rate, IQ Settings + if (mb86a16_write(state, 0x06, 0xdf | (IQINV << 5)) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int FEC_srst(struct mb86a16_state *state) +{ + if (mb86a16_write(state, MB86A16_RESET, 0x02) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int S2T_set(struct mb86a16_state *state, unsigned char S2T) +{ + if (mb86a16_write(state, 0x34, 0x70 | S2T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int S45T_set(struct mb86a16_state *state, unsigned char S4T, unsigned char S5T) +{ + if (mb86a16_write(state, 0x35, 0x00 | (S5T << 4) | S4T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + + +static int mb86a16_set_fe(struct mb86a16_state *state) +{ + u8 agcval, cnmval; + + int i, j; + int fOSC = 0; + int fOSC_start = 0; + int wait_t; + int fcp; + int swp_ofs; + int V[60]; + u8 SIG1MIN; + + unsigned char CREN, AFCEN, AFCEXEN; + unsigned char SIG1; + unsigned char TIMINT1, TIMINT2, TIMEXT; + unsigned char S0T, S1T; + unsigned char S2T; +// unsigned char S2T, S3T; + unsigned char S4T, S5T; + unsigned char AFCEX_L, AFCEX_H; + unsigned char R; + unsigned char VIRM; + unsigned char ETH, VIA; + unsigned char junk; + + int loop; + int ftemp; + int v, vmax, vmin; + int vmax_his, vmin_his; + int swp_freq, prev_swp_freq[20]; + int prev_freq_num; + int signal_dupl; + int afcex_freq; + int signal; + int afcerr; + int temp_freq, delta_freq; + int dagcm[4]; + int smrt_d; +// int freq_err; + int n; + int ret = -1; + int sync; + + dprintk(verbose, MB86A16_INFO, 1, "freq=%d Mhz, symbrt=%d Ksps", state->frequency, state->srate); + + fcp = 5000; // (carrier recovery [kHz]) +// fcp = 3000; + swp_ofs = state->srate / 4; + + for (i = 0; i < 60; i++) + V[i] = -1; + + for (i = 0; i < 20; i++) + prev_swp_freq[i] = 0; + + SIG1MIN = 25; + + for (n = 0; ((n < 3) && (ret == -1)); n++) { + SEQ_set(state, 0); + iq_vt_set(state, 0); + + CREN = 0; + AFCEN = 0; + AFCEXEN = 1; + TIMINT1 = 0; + TIMINT2 = 1; + TIMEXT = 2; + S1T = 0; + S0T = 0; + + if (initial_set(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "initial set failed"); + return -1; + } + if (DAGC_data_set(state, 3, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); + return -1; + } + if (EN_set(state, CREN, AFCEN) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); + return -1; // (0, 0) + } + if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; // (1, smrt) = (1, symbolrate) + } + if (CNTM_set(state, TIMINT1, TIMINT2, TIMEXT) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set error"); + return -1; // (0, 1, 2) + } + if (S01T_set(state, S1T, S0T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); + return -1; // (0, 0) + } + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt info get error"); + return -1; + } + + R = vco_dev_get(state, state->srate); + if (R == 1) + fOSC_start = state->frequency; + + else if (R == 0) { + if (state->frequency % 2 == 0) { + fOSC_start = state->frequency; + } else { + fOSC_start = state->frequency + 1; + if (fOSC_start > 2150) + fOSC_start = state->frequency - 1; + } + } + loop = 1; + ftemp = fOSC_start * 1000; + vmax = 0 ; + while (loop == 1) { + ftemp = ftemp + swp_ofs; + vmax++; + + // Upper bound + if (ftemp > 2150000) { + loop = 0; + vmax--; + } + else if ((ftemp == 2150000) || (ftemp - state->frequency * 1000 >= fcp + state->srate / 4)) + loop = 0; + } + + loop = 1; + ftemp = fOSC_start * 1000; + vmin = 0 ; + while (loop == 1) { + ftemp = ftemp - swp_ofs; + vmin--; + + // Lower bound + if (ftemp < 950000) { + loop = 0; + vmin++; + } + else if ((ftemp == 950000) || (state->frequency * 1000 - ftemp >= fcp + state->srate / 4)) + loop = 0; + } + + wait_t = (8000 + state->srate / 2) / state->srate; + if (wait_t == 0) + wait_t = 1; + + i = 0; + j = 0; + prev_freq_num = 0; + loop = 1; + signal = 0; + vmax_his = 0; + vmin_his = 0; + v = 0; + + while (loop == 1) { + swp_info_get(state, fOSC_start, state->srate, + v, R, swp_ofs, &fOSC, + &afcex_freq, &AFCEX_L, &AFCEX_H); + + if (rf_val_set(state, fOSC, state->srate, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + if (srst(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "srst error"); + return -1; + } + msleep_interruptible(wait_t); + + if (mb86a16_read(state, 0x37, &SIG1) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -1; + } + V[30 + v] = SIG1 ; + swp_freq = swp_freq_calcuation(state, i, v, V, vmax, vmin, + SIG1MIN, fOSC, afcex_freq, + swp_ofs, &SIG1); //changed + + signal_dupl = 0; + for (j = 0; j < prev_freq_num; j++) { + if ((ABS(prev_swp_freq[j] - swp_freq)) < (swp_ofs * 3 / 2)) { + signal_dupl = 1; + dprintk(verbose, MB86A16_INFO, 1, "Probably Duplicate Signal, j = %d", j); + } + } + if ((signal_dupl == 0) && (swp_freq > 0) && (ABS(swp_freq - state->frequency * 1000) < fcp + state->srate / 6)) { + dprintk(verbose, MB86A16_DEBUG, 1, "------ Signal detect ------ [swp_freq=[%07d, srate=%05d]]", swp_freq, state->srate); + prev_swp_freq[prev_freq_num] = swp_freq; + prev_freq_num++; + swp_info_get2(state, state->srate, R, swp_freq, + &afcex_freq, &fOSC, + &AFCEX_L, &AFCEX_H); + + if (rf_val_set(state, fOSC, state->srate, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + signal = signal_det(state, state->srate, &SIG1); + if (signal == 1) { + dprintk(verbose, MB86A16_ERROR, 1, "***** Signal Found *****"); + loop = 0; + } else { + dprintk(verbose, MB86A16_ERROR, 1, "!!!!! No signal !!!!!, try again..."); + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + } + } + if (v > vmax) + vmax_his = 1 ; + if (v < vmin) + vmin_his = 1 ; + i++; + + if ((i % 2 == 1) && (vmax_his == 1)) + i++; + if ((i % 2 == 0) && (vmin_his == 1)) + i++; + + if (i % 2 == 1) + v = (i + 1) / 2; + else + v = -i / 2; + + if ((vmax_his == 1) && (vmin_his == 1)) + loop = 0 ; + } + + if (signal == 1) { + dprintk(verbose, MB86A16_INFO, 1, " Start Freq Error Check"); + S1T = 7 ; + S0T = 1 ; + CREN = 0 ; + AFCEN = 1 ; + AFCEXEN = 0 ; + + if (S01T_set(state, S1T, S0T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); + return -1; + } + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + if (EN_set(state, CREN, AFCEN) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); + return -1; + } + if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; + } + afcex_info_get(state, afcex_freq, &AFCEX_L, &AFCEX_H); + if (afcofs_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCOFS data set error"); + return -1; + } + if (srst(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "srst error"); + return -1; + } + // delay 4~200 + wait_t = 200000 / state->master_clk + 200000 / state->srate; + msleep(wait_t); + afcerr = afcerr_chk(state); + if (afcerr == -1) + return -1; + + swp_freq = fOSC * 1000 + afcerr ; + AFCEXEN = 1 ; + if (state->srate >= 1500) + smrt_d = state->srate / 3; + else + smrt_d = state->srate / 2; + smrt_info_get(state, smrt_d); + if (smrt_set(state, smrt_d) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + if (AFCEXEN_set(state, AFCEXEN, smrt_d) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; + } + R = vco_dev_get(state, smrt_d); + if (DAGC_data_set(state, 2, 0) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); + return -1; + } + for (i = 0; i < 3; i++) { + temp_freq = swp_freq + (i - 1) * state->srate / 8; + swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, smrt_d, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + wait_t = 200000 / state->master_clk + 40000 / smrt_d; + msleep(wait_t); + dagcm[i] = dagcm_val_get(state); + } + if ((dagcm[0] > dagcm[1]) && + (dagcm[0] > dagcm[2]) && + (dagcm[0] - dagcm[1] > 2 * (dagcm[2] - dagcm[1]))) { + + temp_freq = swp_freq - 2 * state->srate / 8; + swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, smrt_d, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set"); + return -1; + } + wait_t = 200000 / state->master_clk + 40000 / smrt_d; + msleep(wait_t); + dagcm[3] = dagcm_val_get(state); + if (dagcm[3] > dagcm[1]) + delta_freq = (dagcm[2] - dagcm[0] + dagcm[1] - dagcm[3]) * state->srate / 300; + else + delta_freq = 0; + } else if ((dagcm[2] > dagcm[1]) && + (dagcm[2] > dagcm[0]) && + (dagcm[2] - dagcm[1] > 2 * (dagcm[0] - dagcm[1]))) { + + temp_freq = swp_freq + 2 * state->srate / 8; + swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, smrt_d, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set"); + return -1; + } + wait_t = 200000 / state->master_clk + 40000 / smrt_d; + msleep(wait_t); + dagcm[3] = dagcm_val_get(state); + if (dagcm[3] > dagcm[1]) + delta_freq = (dagcm[2] - dagcm[0] + dagcm[3] - dagcm[1]) * state->srate / 300; + else + delta_freq = 0 ; + + } else { + delta_freq = 0 ; + } + dprintk(verbose, MB86A16_INFO, 1, "SWEEP Frequency = %d", swp_freq); + swp_freq += delta_freq; + dprintk(verbose, MB86A16_INFO, 1, "Adjusting .., DELTA Freq = %d, SWEEP Freq=%d", delta_freq, swp_freq); + if (ABS(state->frequency * 1000 - swp_freq) > 3800) { + dprintk(verbose, MB86A16_INFO, 1, "NO -- SIGNAL !"); + } else { + + S1T = 0; + S0T = 3; + CREN = 1; + AFCEN = 0; + AFCEXEN = 1; + + if (S01T_set(state, S1T, S0T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); + return -1; + } + if (DAGC_data_set(state, 0, 0) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); + return -1; + } + R = vco_dev_get(state, state->srate); + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + if (EN_set(state, CREN, AFCEN) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); + return -1; + } + if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; + } + swp_info_get2(state, state->srate, R, swp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, state->srate, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + if (srst(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "srst error"); + return -1; + } + wait_t = 7 + (10000 + state->srate / 2) / state->srate; + if (wait_t == 0) + wait_t = 1; + msleep_interruptible(wait_t); + if (mb86a16_read(state, 0x37, &SIG1) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + if (SIG1 > 110) { + S2T = 4; S4T = 1; S5T = 6; ETH = 4; VIA = 6; + wait_t = 7 + (917504 + state->srate / 2) / state->srate; + } else if (SIG1 > 105) { + S2T = 4; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (1048576 + state->srate / 2) / state->srate; + } else if (SIG1 > 85) { + S2T = 5; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (1310720 + state->srate / 2) / state->srate; + } else if (SIG1 > 65) { + S2T = 6; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (1572864 + state->srate / 2) / state->srate; + } else { + S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (2097152 + state->srate / 2) / state->srate; + } + S2T_set(state, S2T); + S45T_set(state, S4T, S5T); + Vi_set(state, ETH, VIA); + srst(state); + msleep_interruptible(wait_t); + sync = sync_chk(state, &VIRM); + dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync); + if (mb86a16_read(state, 0x0d, &state->signal) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + if (VIRM) { + if (VIRM == 4) { // 5/6 + if (SIG1 > 110) + wait_t = ( 786432 + state->srate / 2) / state->srate; + else + wait_t = (1572864 + state->srate / 2) / state->srate; + if (state->srate < 5000) + // FIXME ! , should be a long wait ! + msleep_interruptible(wait_t); + else + msleep_interruptible(wait_t); + + if (sync_chk(state, &junk) == 0) { + iq_vt_set(state, 1); + FEC_srst(state); + } + if (SIG1 > 110) + wait_t = ( 786432 + state->srate / 2) / state->srate; + else + wait_t = (1572864 + state->srate / 2) / state->srate; + + msleep_interruptible(wait_t); + SEQ_set(state, 1); + } else { // 1/2, 2/3, 3/4, 7/8 + if (SIG1 > 110) + wait_t = ( 786432 + state->srate / 2) / state->srate; + else + wait_t = (1572864 + state->srate / 2) / state->srate; + + msleep_interruptible(wait_t); + SEQ_set(state, 1); + } + } else { + dprintk(verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); + SEQ_set(state, 1); + } + } + } else { + dprintk (verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); + } + + sync = sync_chk(state, &junk); + if (sync) { + dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******"); + freqerr_chk(state, state->frequency, state->srate, 1); + } + } + + mb86a16_read(state, 0x15, &agcval); + mb86a16_read(state, 0x26, &cnmval); + dprintk(verbose, MB86A16_INFO, 1, "AGC = %02x CNM = %02x", agcval, cnmval); + + return ret; +} + +static int mb86a16_send_diseqc_msg(struct dvb_frontend *fe, + struct dvb_diseqc_master_cmd *cmd) +{ + struct mb86a16_state *state = fe->demodulator_priv; + int i; + u8 regs; + + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0) + goto err; + if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0) + goto err; + + regs = 0x18; + + if (cmd->msg_len > 5 || cmd->msg_len < 4) + return -EINVAL; + + for (i = 0; i < cmd->msg_len; i++) { + if (mb86a16_write(state, regs, cmd->msg[i]) < 0) + goto err; + + regs++; + } + i += 0x90; + + msleep_interruptible(10); + + if (mb86a16_write(state, MB86A16_DCC1, i) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int mb86a16_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) +{ + struct mb86a16_state *state = fe->demodulator_priv; + + switch (burst) { + case SEC_MINI_A: + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | + MB86A16_DCC1_TBEN | + MB86A16_DCC1_TBO) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + break; + case SEC_MINI_B: + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | + MB86A16_DCC1_TBEN) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + break; + } + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int mb86a16_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +{ + struct mb86a16_state *state = fe->demodulator_priv; + + switch (tone) { + case SEC_TONE_ON: + if (mb86a16_write(state, MB86A16_TONEOUT2, 0x00) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | + MB86A16_DCC1_CTOE) < 0) + + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + break; + case SEC_TONE_OFF: + if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0) + goto err; + break; + default: + return -EINVAL; + } + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +#define MB86A16_FE_ALGO 1 + +static int mb86a16_frontend_algo(struct dvb_frontend *fe) +{ + return MB86A16_FE_ALGO; +} + +static int mb86a16_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p, + unsigned int mode_flags, + int *delay, + fe_status_t *status) +{ + int ret = 0; + struct mb86a16_state *state = fe->demodulator_priv; + + if (p != NULL) { + state->frequency = p->frequency / 1000; + state->srate = p->u.qpsk.symbol_rate / 1000; + ret = mb86a16_set_fe(state); + } + if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) + mb86a16_read_status(fe, status); + + *delay = HZ/3000; + + return ret; +} + +static void mb86a16_release(struct dvb_frontend *fe) +{ + struct mb86a16_state *state = fe->demodulator_priv; + kfree(state); +} + +static int mb86a16_init(struct dvb_frontend *fe) +{ + return 0; +} + +static int mb86a16_sleep(struct dvb_frontend *fe) +{ + return 0; +} + +static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + return 0; +} + +static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + *strength = 0; + + return 0; +} + +struct cnr { + u8 cn_reg; + u8 cn_val; +}; + +static const struct cnr cnr_tab[] = { + { 35, 2 }, + { 40, 3 }, + { 50, 4 }, + { 60, 5 }, + { 70, 6 }, + { 80, 7 }, + { 92, 8 }, + { 103, 9 }, + { 115, 10 }, + { 138, 12 }, + { 162, 15 }, + { 180, 18 }, + { 185, 19 }, + { 189, 20 }, + { 195, 22 }, + { 199, 24 }, + { 201, 25 }, + { 202, 26 }, + { 203, 27 }, + { 205, 28 }, + { 208, 30 } +}; + +static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct mb86a16_state *state = fe->demodulator_priv; + int i = 0; + int low_tide = 2, high_tide = 30, q_level; + u8 cn; + + if (mb86a16_read(state, 0x26, &cn) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + for (i = 0; i < ARRAY_SIZE(cnr_tab); i++) { + if (cn < cnr_tab[i].cn_reg) { + *snr = cnr_tab[i].cn_val; + break; + } + } + q_level = (*snr * 100) / (high_tide - low_tide); + dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level); + + return 0; +} + +static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + return 0; +} + +static struct dvb_frontend_ops mb86a16_ops = { + .info = { + .name = "Fujitsu MB86A16 DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 125, + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | + FE_CAN_FEC_7_8 | FE_CAN_QPSK | + FE_CAN_FEC_AUTO + }, + .release = mb86a16_release, + .tune = mb86a16_set_frontend, + .read_status = mb86a16_read_status, + .get_frontend_algo = mb86a16_frontend_algo, + .init = mb86a16_init, + .sleep = mb86a16_sleep, + .read_status = mb86a16_read_status, + + .read_ber = mb86a16_read_ber, + .read_signal_strength = mb86a16_read_signal_strength, + .read_snr = mb86a16_read_snr, + .read_ucblocks = mb86a16_read_ucblocks, + + .diseqc_send_master_cmd = mb86a16_send_diseqc_msg, + .diseqc_send_burst = mb86a16_send_diseqc_burst, + .set_tone = mb86a16_set_tone, +}; + +struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, + struct i2c_adapter *i2c_adap) +{ + u8 dev_id = 0; + struct mb86a16_state *state = NULL; + + state = kmalloc(sizeof (struct mb86a16_state), GFP_KERNEL); + if (state == NULL) + goto error; + + state->config = config; + state->i2c_adap = i2c_adap; + + mb86a16_read(state, 0x7f, &dev_id); + if (dev_id != 0xfe) + goto error; + + memcpy(&state->frontend.ops, &mb86a16_ops, sizeof (struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + state->frontend.ops.set_voltage = state->config->set_voltage; + + return &state->frontend; +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(mb86a16_attach); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Manu Abraham"); diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb/frontends/mb86a16.h new file mode 100644 index 00000000000..b7545d0343f --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a16.h @@ -0,0 +1,38 @@ +/* + Fujitsu MB86A16 DVB-S/DSS DC Receiver driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MB86A16_H +#define __MB86A16_H + +#include +#include "dvb_frontend.h" + + +struct mb86a16_config { + u8 demod_address; + + int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); +}; + +extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, + struct i2c_adapter *i2c_adap); + + +#endif //__MB86A16_H diff --git a/drivers/media/dvb/frontends/mb86a16_priv.h b/drivers/media/dvb/frontends/mb86a16_priv.h new file mode 100644 index 00000000000..5de57006806 --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a16_priv.h @@ -0,0 +1,151 @@ +/* + Fujitsu MB86A16 DVB-S/DSS DC Receiver driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MB86A16_PRIV_H +#define __MB86A16_PRIV_H + +#define MB86A16_TSOUT 0x00 +#define MB86A16_TSOUT_HIZSEL (0x01 << 5) +#define MB86A16_TSOUT_HIZCNTI (0x01 << 4) +#define MB86A16_TSOUT_MODE (0x01 << 3) +#define MB86A16_TSOUT_ORDER (0x01 << 2) +#define MB86A16_TSOUT_ERROR (0x01 << 1) +#define Mb86A16_TSOUT_EDGE (0x01 << 0) + +#define MB86A16_FEC 0x01 +#define MB86A16_FEC_FSYNC (0x01 << 5) +#define MB86A16_FEC_PCKB8 (0x01 << 4) +#define MB86A16_FEC_DVDS (0x01 << 3) +#define MB86A16_FEC_EREN (0x01 << 2) +#define Mb86A16_FEC_RSEN (0x01 << 1) +#define MB86A16_FEC_DIEN (0x01 << 0) + +#define MB86A16_AGC 0x02 +#define MB86A16_AGC_AGMD (0x01 << 6) +#define MB86A16_AGC_AGCW (0x0f << 2) +#define MB86A16_AGC_AGCP (0x01 << 1) +#define MB86A16_AGC_AGCR (0x01 << 0) + +#define MB86A16_SRATE1 0x03 +#define MB86A16_SRATE1_DECI (0x07 << 2) +#define MB86A16_SRATE1_CSEL (0x01 << 1) +#define MB86A16_SRATE1_RSEL (0x01 << 0) + +#define MB86A16_SRATE2 0x04 +#define MB86A16_SRATE2_STOFSL (0xff << 0) + +#define MB86A16_SRATE3 0x05 +#define MB86A16_SRATE2_STOFSH (0xff << 0) + +#define MB86A16_VITERBI 0x06 +#define MB86A16_FRAMESYNC 0x07 +#define MB86A16_CRLFILTCOEF1 0x08 +#define MB86A16_CRLFILTCOEF2 0x09 +#define MB86A16_STRFILTCOEF1 0x0a +#define MB86A16_STRFILTCOEF2 0x0b +#define MB86A16_RESET 0x0c +#define MB86A16_STATUS 0x0d +#define MB86A16_AFCML 0x0e +#define MB86A16_AFCMH 0x0f +#define MB86A16_BERMON 0x10 +#define MB86A16_BERTAB 0x11 +#define MB86A16_BERLSB 0x12 +#define MB86A16_BERMID 0x13 +#define MB86A16_BERMSB 0x14 +#define MB86A16_AGCM 0x15 + +#define MB86A16_DCC1 0x16 +#define MB86A16_DCC1_DISTA (0x01 << 7) +#define MB86A16_DCC1_PRTY (0x01 << 6) +#define MB86A16_DCC1_CTOE (0x01 << 5) +#define MB86A16_DCC1_TBEN (0x01 << 4) +#define MB86A16_DCC1_TBO (0x01 << 3) +#define MB86A16_DCC1_NUM (0x07 << 0) + +#define MB86A16_DCC2 0x17 +#define MB86A16_DCC2_DCBST (0x01 << 0) + +#define MB86A16_DCC3 0x18 +#define MB86A16_DCC3_CODE0 (0xff << 0) + +#define MB86A16_DCC4 0x19 +#define MB86A16_DCC4_CODE1 (0xff << 0) + +#define MB86A16_DCC5 0x1a +#define MB86A16_DCC5_CODE2 (0xff << 0) + +#define MB86A16_DCC6 0x1b +#define MB86A16_DCC6_CODE3 (0xff << 0) + +#define MB86A16_DCC7 0x1c +#define MB86A16_DCC7_CODE4 (0xff << 0) + +#define MB86A16_DCC8 0x1d +#define MB86A16_DCC8_CODE5 (0xff << 0) + +#define MB86A16_DCCOUT 0x1e +#define MB86A16_DCCOUT_DISEN (0x01 << 0) + +#define MB86A16_TONEOUT1 0x1f +#define MB86A16_TONE_TDIVL (0xff << 0) + +#define MB86A16_TONEOUT2 0x20 +#define MB86A16_TONE_TMD (0x03 << 2) +#define MB86A16_TONE_TDIVH (0x03 << 0) + +#define MB86A16_FREQ1 0x21 +#define MB86A16_FREQ2 0x22 +#define MB86A16_FREQ3 0x23 +#define MB86A16_FREQ4 0x24 +#define MB86A16_FREQSET 0x25 +#define MB86A16_CNM 0x26 +#define MB86A16_PORT0 0x27 +#define MB86A16_PORT1 0x28 +#define MB86A16_DRCFILT 0x29 +#define MB86A16_AFC 0x2a +#define MB86A16_AFCEXL 0x2b +#define MB86A16_AFCEXH 0x2c +#define MB86A16_DAGC 0x2d +#define MB86A16_SEQMODE 0x32 +#define MB86A16_S0S1T 0x33 +#define MB86A16_S2S3T 0x34 +#define MB86A16_S4S5T 0x35 +#define MB86A16_CNTMR 0x36 +#define MB86A16_SIG1 0x37 +#define MB86A16_SIG2 0x38 +#define MB86A16_VIMAG 0x39 +#define MB86A16_VISET1 0x3a +#define MB86A16_VISET2 0x3b +#define MB86A16_VISET3 0x3c +#define MB86A16_FAGCS1 0x3d +#define MB86A16_FAGCS2 0x3e +#define MB86A16_FAGCS3 0x3f +#define MB86A16_FAGCS4 0x40 +#define MB86A16_FAGCS5 0x41 +#define MB86A16_FAGCS6 0x42 +#define MB86A16_CRM 0x43 +#define MB86A16_STRM 0x44 +#define MB86A16_DAGCML 0x45 +#define MB86A16_DAGCMH 0x46 +#define MB86A16_QPSKTST 0x49 +#define MB86A16_DISTMON 0x52 +#define MB86A16_VERSION 0x7f + +#endif //__MB86A16_PRIV_H diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig new file mode 100644 index 00000000000..4ba16d0ad96 --- /dev/null +++ b/drivers/media/dvb/mantis/Kconfig @@ -0,0 +1,13 @@ +config DVB_MANTIS + tristate "MANTIS based cards" + depends on DVB_CORE && PCI && I2C + select DVB_MB86A16 + select DVB_CU1216 + select DVB_ZL10353 + select DVB_STV0299 + select DVB_PLL + help + Support for PCI cards based on the Mantis PCI bridge. + Say Y when you have a Mantis based DVB card and want to use it. + + If unsure say N. diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile new file mode 100644 index 00000000000..a980ff2382b --- /dev/null +++ b/drivers/media/dvb/mantis/Makefile @@ -0,0 +1,7 @@ +mantis-objs = mantis_core.o mantis_dma.o mantis_pci.o mantis_i2c.o \ + mantis_dvb.o mantis_vp1033.o mantis_vp1034.o mantis_vp2033.o \ + mantis_vp3030.o + +obj-$(CONFIG_DVB_MANTIS) += mantis.o + +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h new file mode 100644 index 00000000000..ba360f88496 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -0,0 +1,135 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_COMMON_H +#define __MANTIS_COMMON_H + +#include +#include +#include +#include + +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dmxdev.h" +#include "dvb_frontend.h" +#include "dvb_net.h" +#include +#include "mantis_reg.h" + +#define MANTIS_ERROR 0 +#define MANTIS_NOTICE 1 +#define MANTIS_INFO 2 +#define MANTIS_DEBUG 3 + +#define dprintk(x, y, z, format, arg...) do { \ + if (z) { \ + if ((x > MANTIS_ERROR) && (x > y)) \ + printk(KERN_ERR "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + else if ((x > MANTIS_NOTICE) && (x > y)) \ + printk(KERN_NOTICE "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + else if ((x > MANTIS_INFO) && (x > y)) \ + printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + else if ((x > MANTIS_DEBUG) && (x > y)) \ + printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + } else { \ + if (x > y) \ + printk(format , ##arg); \ + } \ +} while(0) + +#define mwrite(dat, addr) writel((dat), addr) +#define mread(addr) readl(addr) + +#define mmwrite(dat, addr) mwrite((dat), (mantis->mantis_mmio + (addr))) +#define mmread(addr) mread(mantis->mantis_mmio + (addr)) +#define mmand(dat, addr) mmwrite((dat) & mmread(addr), addr) +#define mmor(dat, addr) mmwrite((dat) | mmread(addr), addr) +#define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr) + + +struct mantis_pci { + /* PCI stuff */ + u16 vendor_id; + u16 device_id; + u8 latency; + + struct pci_dev *pdev; + + unsigned long mantis_addr; + volatile void __iomem *mantis_mmio; + + u8 irq; + u8 revision; + + unsigned int num; + u16 ts_size; + + /* RISC Core */ + u32 finished_block; + u32 last_block; + u32 line_bytes; + u32 line_count; + u32 risc_pos; + u8 *buf_cpu; + dma_addr_t buf_dma; + u32 *risc_cpu; + dma_addr_t risc_dma; + + struct tasklet_struct tasklet; + + struct i2c_adapter adapter; + int i2c_rc; + wait_queue_head_t i2c_wq; + + /* DVB stuff */ + struct dvb_adapter dvb_adapter; + struct dvb_frontend *fe; + struct dvb_demux demux; + struct dmxdev dmxdev; + struct dmx_frontend fe_hw; + struct dmx_frontend fe_mem; + struct dvb_net dvbnet; + + u8 feeds; + + struct mantis_config *config; + + u32 mantis_int_stat; + u32 mantis_int_mask; + + /* board specific */ + u8 mac_address[8]; + u32 sub_vendor_id; + u32 sub_device_id; + + /* A12 A13 A14 */ + int gpio_status;}; + +extern unsigned int verbose; +extern unsigned int devs; +extern unsigned int i2c; +extern int mantis_dvb_init(struct mantis_pci *mantis); +extern int mantis_frontend_init(struct mantis_pci *mantis); +extern int mantis_dvb_exit(struct mantis_pci *mantis); +extern void mantis_dma_xfer(unsigned long data); +extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); + +#endif //__MANTIS_COMMON_H diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c new file mode 100644 index 00000000000..11122775245 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -0,0 +1,215 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_core.h" + + +static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +{ + int err; + struct i2c_msg msg[] = { + { + .addr = 0x50, + .flags = 0, + .buf = data, + .len = 1 + },{ + .addr = 0x50, + .flags = I2C_M_RD, + .buf = data, + .len = length + }, + }; + if ((err = i2c_transfer(&mantis->adapter, msg, 2)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >", + err, data[0], data[1]); + + return err; + } + msleep_interruptible(2); + + return 0; +} + +static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +{ + int err; + + struct i2c_msg msg = { + .addr = 0x50, + .flags = 0, + .buf = data, + .len = length + }; + + if ((err = i2c_transfer(&mantis->adapter, &msg, 1)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", + err, length, data[0], data[1]); + + return err; + } + + return 0; +} + +static int get_subdevice_id(struct mantis_pci *mantis) +{ + int err; + static u8 sub_device_id[2]; + + mantis->sub_device_id = 0; + sub_device_id[0] = 0xfc; + if ((err = read_eeprom_byte(mantis, &sub_device_id[0], 2)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); + return err; + } + mantis->sub_device_id = (sub_device_id[0] << 8) | sub_device_id[1]; + dprintk(verbose, MANTIS_ERROR, 1, "Sub Device ID=[0x%04x]", + mantis->sub_device_id); + + return 0; +} + +static int get_subvendor_id(struct mantis_pci *mantis) +{ + int err; + static u8 sub_vendor_id[2]; + + mantis->sub_vendor_id = 0; + sub_vendor_id[0] = 0xfe; + if ((err = read_eeprom_byte(mantis, &sub_vendor_id[0], 2)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); + return err; + } + mantis->sub_vendor_id = (sub_vendor_id[0] << 8) | sub_vendor_id[1]; + dprintk(verbose, MANTIS_ERROR, 1, "Sub Vendor ID=[0x%04x]", + mantis->sub_vendor_id); + + return 0; +} + +static int get_mac_address(struct mantis_pci *mantis) +{ + int err; + + mantis->mac_address[0] = 0x08; + if ((err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); + + return err; + } + dprintk(verbose, MANTIS_ERROR, 1, + "MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]", + mantis->mac_address[0], mantis->mac_address[1], + mantis->mac_address[2], mantis->mac_address[3], + mantis->mac_address[4], mantis->mac_address[5]); + + return 0; +} + + +int mantis_core_init(struct mantis_pci *mantis) +{ + int err = 0; + + if ((err = mantis_i2c_init(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed"); + return err; + } + if ((err = get_mac_address(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed"); + return err; + } + if ((err = get_subvendor_id(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "get Sub vendor ID failed"); + return err; + } + if ((err = get_subdevice_id(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "get Sub device ID failed"); + return err; + } + if ((err = mantis_dma_init(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed"); + return err; + } + if ((err = mantis_dvb_init(mantis)) < 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed"); + return err; + } + + return 0; +} + +int mantis_core_exit(struct mantis_pci *mantis) +{ + + mantis_dma_stop(mantis); + dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping"); + if (mantis_dma_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); + if (mantis_dvb_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "DVB exit failed"); + if (mantis_i2c_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "I2C adapter delete.. failed"); + + return 0; +} + +void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) +{ + u32 reg; + + if (value) + reg = 0x0000; + else + reg = 0xffff; + + reg = (value << bitpos); + + mmwrite(mmread(MANTIS_GPIF_ADDR) | reg, MANTIS_GPIF_ADDR); + mmwrite(0x00, MANTIS_GPIF_DOUT); + udelay(100); + mmwrite(mmread(MANTIS_GPIF_ADDR) | reg, MANTIS_GPIF_ADDR); + mmwrite(0x00, MANTIS_GPIF_DOUT); +} + + +//direction = 0 , no CI passthrough ; 1 , CI passthrough +void mantis_set_direction(struct mantis_pci *mantis, int direction) +{ + u32 reg; + + reg = mmread(0x28); + dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup"); + if (direction == 0x01) { //to CI + reg |= 0x04; + mmwrite(reg, 0x28); + reg &= 0xff - 0x04; + mmwrite(reg, 0x28); + } else { + reg &= 0xff - 0x04; + mmwrite(reg, 0x28); + reg |= 0x04; + mmwrite(reg, 0x28); + } +} diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/dvb/mantis/mantis_core.h new file mode 100644 index 00000000000..31b2a756d99 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_core.h @@ -0,0 +1,61 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_CORE_H +#define __MANTIS_CORE_H + +#include "mantis_common.h" + + +#define FE_TYPE_SAT 0 +#define FE_TYPE_CAB 1 +#define FE_TYPE_TER 2 + +#define FE_TYPE_TS204 0 +#define FE_TYPE_TS188 1 + + +struct vendorname { + __u8 *sub_vendor_name; + __u32 sub_vendor_id; +}; + +struct devicetype { + __u8 *sub_device_name; + __u32 sub_device_id; + __u8 device_type; + __u32 type_flags; +}; + + +extern int mantis_dma_init(struct mantis_pci *mantis); +extern int mantis_dma_exit(struct mantis_pci *mantis); +extern void mantis_dma_start(struct mantis_pci *mantis); +extern void mantis_dma_stop(struct mantis_pci *mantis); +extern int mantis_i2c_init(struct mantis_pci *mantis); +extern int mantis_i2c_exit(struct mantis_pci *mantis); +extern int mantis_core_init(struct mantis_pci *mantis); +extern int mantis_core_exit(struct mantis_pci *mantis); +//extern void mantis_fe_powerup(struct mantis_pci *mantis); +//extern void mantis_fe_powerdown(struct mantis_pci *mantis); +//extern void mantis_fe_reset(struct dvb_frontend *fe); +extern void mantis_set_direction(struct mantis_pci *mantis, int direction); + +#endif //__MANTIS_CORE_H diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c new file mode 100644 index 00000000000..9e3aa5ec164 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -0,0 +1,238 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include "mantis_common.h" + +#define RISC_WRITE (0x01 << 28) +#define RISC_JUMP (0x07 << 28) +#define RISC_IRQ (0x01 << 24) + +#define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16)) +#define RISC_FLUSH() mantis->risc_pos = 0 +#define RISC_INSTR(opcode) mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode) + +#define MANTIS_BUF_SIZE 64 * 1024 +#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4) +#define MANTIS_BLOCK_COUNT (1 << 4) +#define MANTIS_RISC_SIZE PAGE_SIZE + +int mantis_dma_exit(struct mantis_pci *mantis) +{ + if (mantis->buf_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "DMA=0x%lx cpu=0x%p size=%d", + (unsigned long) mantis->buf_dma, + mantis->buf_cpu, + MANTIS_BUF_SIZE); + + pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE, + mantis->buf_cpu, mantis->buf_dma); + + mantis->buf_cpu = NULL; + } + if (mantis->risc_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "RISC=0x%lx cpu=0x%p size=%lx", + (unsigned long) mantis->risc_dma, + mantis->risc_cpu, + MANTIS_RISC_SIZE); + + pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE, + mantis->risc_cpu, mantis->risc_dma); + + mantis->risc_cpu = NULL; + } + + return 0; +} + +static inline int mantis_alloc_buffers(struct mantis_pci *mantis) +{ + if (!mantis->buf_cpu) { + mantis->buf_cpu = pci_alloc_consistent(mantis->pdev, + MANTIS_BUF_SIZE, + &mantis->buf_dma); + if (!mantis->buf_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "DMA buffer allocation failed"); + + goto err; + } + dprintk(verbose, MANTIS_ERROR, 1, + "DMA=0x%lx cpu=0x%p size=%d", + (unsigned long) mantis->buf_dma, + mantis->buf_cpu, MANTIS_BUF_SIZE); + } + if (!mantis->risc_cpu) { + mantis->risc_cpu = pci_alloc_consistent(mantis->pdev, + MANTIS_RISC_SIZE, + &mantis->risc_dma); + + if (!mantis->risc_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "RISC program allocation failed"); + + mantis_dma_exit(mantis); + + goto err; + } + dprintk(verbose, MANTIS_ERROR, 1, + "RISC=0x%lx cpu=0x%p size=%lx", + (unsigned long) mantis->risc_dma, + mantis->risc_cpu, MANTIS_RISC_SIZE); + } + + return 0; +err: + dprintk(verbose, MANTIS_ERROR, 1, "Out of memory (?) ....."); + return -ENOMEM; +} + +static inline int mantis_calc_lines(struct mantis_pci *mantis) +{ + mantis->line_bytes = MANTIS_BLOCK_BYTES; + mantis->line_count = MANTIS_BLOCK_COUNT; + + while (mantis->line_bytes > 4095) { + mantis->line_bytes >>= 1; + mantis->line_count <<= 1; + } + + dprintk(verbose, MANTIS_DEBUG, 1, + "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]", + MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count); + + if (mantis->line_count > 255) { + dprintk(verbose, MANTIS_ERROR, 1, "Buffer size error"); + return -EINVAL; + } + + return 0; +} + +int mantis_dma_init(struct mantis_pci *mantis) +{ + int err = 0; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DMA init"); + if (mantis_alloc_buffers(mantis) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Error allocating DMA buffer"); + + // Stop RISC Engine +// mmwrite(mmread(MANTIS_DMA_CTL) & ~MANTIS_RISC_EN, MANTIS_DMA_CTL); + mmwrite(0, MANTIS_DMA_CTL); + + goto err; + } + if ((err = mantis_calc_lines(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis calc lines failed"); + + goto err; + } + + return 0; +err: + return err; +} + + + +static inline void mantis_risc_program(struct mantis_pci *mantis) +{ + u32 buf_pos = 0; + u32 line; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis create RISC program"); + RISC_FLUSH(); + + dprintk(verbose, MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u", + mantis->line_count, mantis->line_bytes); + + for (line = 0; line < mantis->line_count; line++) { + dprintk(verbose, MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line); + if (!(buf_pos % MANTIS_BLOCK_BYTES)) { + RISC_INSTR(RISC_WRITE | + RISC_IRQ | + RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) + + (MANTIS_BLOCK_COUNT - 1)) % + MANTIS_BLOCK_COUNT) | + mantis->line_bytes); + } else { + RISC_INSTR(RISC_WRITE | mantis->line_bytes); + } + RISC_INSTR(mantis->buf_dma + buf_pos); + buf_pos += mantis->line_bytes; + } + RISC_INSTR(RISC_JUMP); + RISC_INSTR(mantis->risc_dma); +} + +void mantis_dma_start(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Start DMA engine"); + + mantis_risc_program(mantis); + mmwrite(cpu_to_le32(mantis->risc_dma), MANTIS_RISC_START); + mmwrite(MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); + + mmwrite(0, MANTIS_DMA_CTL); + mantis->last_block = mantis->finished_block = 0; + + mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK); + + mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN + | MANTIS_RISC_EN, MANTIS_DMA_CTL); + +} + +void mantis_dma_stop(struct mantis_pci *mantis) +{ + u32 stat = 0, mask = 0; + + stat = mmread(MANTIS_INT_STAT); + mask = mmread(MANTIS_INT_MASK); + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); + + mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | + MANTIS_DCAP_EN | + MANTIS_RISC_EN)), MANTIS_DMA_CTL); + + mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT); + + mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI | + MANTIS_INT_RISCEN), MANTIS_INT_MASK); +} + + +void mantis_dma_xfer(unsigned long data) +{ + struct mantis_pci *mantis = (struct mantis_pci *) data; + + while (mantis->last_block != mantis->finished_block) { + dprintk(verbose, MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", + mantis->last_block, mantis->finished_block); + + (mantis->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) + (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); + mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT; + } +} diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c new file mode 100644 index 00000000000..5830d4a7bda --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -0,0 +1,304 @@ +/* + Mantis PCI bridge driver + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include "mantis_common.h" +#include "mantis_core.h" + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "mantis_vp1033.h" +#include "mantis_vp1034.h" +#include "mantis_vp2033.h" +#include "mantis_vp3030.h" + +/* Tuner power supply control */ +void mantis_fe_powerup(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power ON"); + gpio_set_bits(mantis, 0x0c, 1); + msleep_interruptible(100); + gpio_set_bits(mantis, 0x0c, 1); + msleep_interruptible(100); +} + +void mantis_fe_powerdown(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power OFF"); + gpio_set_bits(mantis, 0x0c, 0); +} + +static int mantis_fe_reset(struct dvb_frontend *fe) +{ + struct mantis_pci *mantis = fe->dvb->priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + + return 0; +} + +static int mantis_frontend_reset(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + + return 0; +} + +static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct mantis_pci *mantis = dvbdmx->priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Start feed"); + if (!dvbdmx->dmx.frontend) { + dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); + return -EINVAL; + } + mantis->feeds++; + dprintk(verbose, MANTIS_DEBUG, 1, + "mantis start feed, feeds=%d", + mantis->feeds); + + if (mantis->feeds == 1) { + dprintk(verbose, MANTIS_DEBUG, 1, "mantis start feed & dma"); + printk("mantis start feed & dma\n"); + mantis_dma_start(mantis); + } + + return mantis->feeds; +} + +static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct mantis_pci *mantis = dvbdmx->priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); + if (!dvbdmx->dmx.frontend) { + dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); + return -EINVAL; + } + mantis->feeds--; + if (mantis->feeds == 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "mantis stop feed and dma"); + printk("mantis stop feed and dma\n"); + mantis_dma_stop(mantis); + } + return 0; +} + +int __devinit mantis_dvb_init(struct mantis_pci *mantis) +{ + int result; + + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_register_adapter"); + if (dvb_register_adapter(&mantis->dvb_adapter, + "Mantis dvb adapter", THIS_MODULE, + &mantis->pdev->dev) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, "Error registering adapter"); + return -ENODEV; + } + mantis->dvb_adapter.priv = mantis; + mantis->demux.dmx.capabilities = DMX_TS_FILTERING | + DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING; + + mantis->demux.priv = mantis; + mantis->demux.filternum = 256; + mantis->demux.feednum = 256; + mantis->demux.start_feed = mantis_dvb_start_feed; + mantis->demux.stop_feed = mantis_dvb_stop_feed; + mantis->demux.write_to_decoder = NULL; + mantis->ts_size = 1; //188 + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmx_init"); + if ((result = dvb_dmx_init(&mantis->demux)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err0; + } + mantis->dmxdev.filternum = 256; + mantis->dmxdev.demux = &mantis->demux.dmx; + mantis->dmxdev.capabilities = 0; + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmxdev_init"); + if ((result = dvb_dmxdev_init(&mantis->dmxdev, + &mantis->dvb_adapter)) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmxdev_init failed, ERROR=%d", result); + goto err1; + } + mantis->fe_hw.source = DMX_FRONTEND_0; + if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, + &mantis->fe_hw)) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err2; + } + mantis->fe_mem.source = DMX_MEMORY_FE; + if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, + &mantis->fe_mem)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err3; + } + if ((result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, + &mantis->fe_hw)) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err4; + } + dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); + tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); + mantis_frontend_init(mantis); + return 0; + + /* Error conditions .. */ +err4: + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); +err3: + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); +err2: + dvb_dmxdev_release(&mantis->dmxdev); +err1: + dvb_dmx_release(&mantis->demux); +err0: + dvb_unregister_adapter(&mantis->dvb_adapter); + + return result; +} + +#define MANTIS_VP_1027_DVB_S 0x0013 +#define MANTIS_VP_1033_DVB_S 0x0016 +#define MANTIS_VP_1034_DVB_S 0x0014 +#define MANTIS_VP_1040_DVB_S2 +#define MANTIS_VP_1041_DVB_S2 +#define MANTIS_VP_2033_DVB_C 0x0008 +#define MANTIS_VP_3024_DVB_T 0x0009 +#define MANTIS_VP_3030_DVB_T 0x0024 + +int __devinit mantis_frontend_init(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis frontend Init"); + mantis_fe_powerup(mantis); + mantis_frontend_reset(mantis); + dprintk(verbose, MANTIS_DEBUG, 1, "Device ID=%02x", mantis->sub_device_id); + switch (mantis->sub_device_id) { + case MANTIS_VP_1033_DVB_S: // VP-1033 + dprintk(verbose, MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); + mantis->fe = stv0299_attach(&lgtdqcs001f_config, + &mantis->adapter); + + if (mantis->fe) { + mantis->fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; + dprintk(verbose, MANTIS_ERROR, 1, + "found STV0299 DVB-S frontend @ 0x%02x", + lgtdqcs001f_config.demod_address); + + dprintk(verbose, MANTIS_ERROR, 1, + "Mantis DVB-S STV0299 frontend attach success"); + } + break; + case MANTIS_VP_1034_DVB_S: // VP-1034 + dprintk(verbose, MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); + mantis->fe = mb86a16_attach(&vp1034_config, &mantis->adapter); + if (mantis->fe) { + dprintk(verbose, MANTIS_ERROR, 1, + "found MB86A16 DVB-S/DSS frontend @0x%02x", + vp1034_config.demod_address); + + } + break; + case MANTIS_VP_2033_DVB_C: // VP-2033 + dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + mantis->fe = cu1216_attach(&philips_cu1216_config, &mantis->adapter); + if (mantis->fe) { + mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; + dprintk(verbose, MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend @ 0x%02x", + philips_cu1216_config.demod_address); + + dprintk(verbose, MANTIS_ERROR, 1, + "Mantis DVB-C Philips CU1216 frontend attach success"); + + } + break; + default: + dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", + mantis->sub_device_id); + + return -ENODEV; + } + if (mantis->fe == NULL) { + dprintk(verbose, MANTIS_ERROR, 1, "!!! NO Frontends found !!!"); + return -ENODEV; + } else { + if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) { + dprintk(verbose, MANTIS_ERROR, 1, + "ERROR: Frontend registration failed"); + + if (mantis->fe->ops.release) + mantis->fe->ops.release(mantis->fe); + + mantis->fe = NULL; + return -ENODEV; + } + } + + return 0; +} + +int __devexit mantis_dvb_exit(struct mantis_pci *mantis) +{ + tasklet_kill(&mantis->tasklet); + dvb_net_release(&mantis->dvbnet); + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); + dvb_dmxdev_release(&mantis->dmxdev); + dvb_dmx_release(&mantis->demux); + + if (mantis->fe) + dvb_unregister_frontend(mantis->fe); + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_unregister_adapter"); + dvb_unregister_adapter(&mantis->dvb_adapter); + + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c new file mode 100644 index 00000000000..cfecb344bb7 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -0,0 +1,189 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mantis_common.h" + +#define I2C_HW_B_MANTIS 0x1c + +static int mantis_ack_wait(struct mantis_pci *mantis) +{ + int rc = 0; + + if (wait_event_interruptible_timeout(mantis->i2c_wq, + mantis->mantis_int_stat & MANTIS_INT_I2CRACK, + msecs_to_jiffies(50)) == -ERESTARTSYS) + + rc = -EREMOTEIO; +/* + // Wait till we are done + while (mantis->mantis_int_stat & MANTIS_INT_I2CRACK){ + if (mantis->mantis_int_stat & MANTIS_INT_I2CDONE) { + mantis->mantis_int_stat &= ~MANTIS_INT_I2CRACK; +// dprintk(verbose, MANTIS_DEBUG, 1, "SLAVE RACK 'ed .. Waiting for I2CDONE"); + break; + } + } + + if (mantis->mantis_int_stat & MANTIS_INT_I2CDONE) { +// dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Int I2CDONE"); + rc = 1; + } + + mantis->mantis_int_stat &= ~MANTIS_INT_I2CDONE; +*/ + // .. + if (mantis->mantis_int_stat & MANTIS_INT_I2CRACK) + msleep_interruptible(10); + + return rc; +} + +static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) +{ + u32 rxd, i; + + dprintk(verbose, MANTIS_DEBUG, 1, "Address=[0x%02x]", msg->addr); + for (i = 0; i < msg->len; i++) { + rxd = (msg->addr << 25) | (1 << 24) + | MANTIS_I2C_RATE_3 + | MANTIS_I2C_STOP + | MANTIS_I2C_PGMODE; + + if (i == (msg->len - 1)) + rxd &= ~MANTIS_I2C_STOP; + + mmwrite(rxd, MANTIS_I2CDATA_CTL); + if (mantis_ack_wait(mantis) < 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); + return -EIO; + } + rxd = mmread(MANTIS_I2CDATA_CTL); + msg->buf[i] = (u8)((rxd >> 8) & 0xFF); + dprintk(verbose, MANTIS_DEBUG, 1, + "Data=[0x%02x]", i, msg->buf[i]); + + msleep_interruptible(2); + } + + return 0; +} + +static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg) +{ + int i; + u32 txd = 0; + + dprintk(verbose, MANTIS_DEBUG, 1, "Address=[0x%02x]", msg->addr); + for (i = 0; i < msg->len; i++) { + dprintk(verbose, MANTIS_DEBUG, 1, "Data=[0x%02x]", i, msg->buf[i]); + txd = (msg->addr << 25) | (msg->buf[i] << 8) + | MANTIS_I2C_RATE_3 + | MANTIS_I2C_STOP + | MANTIS_I2C_PGMODE; + + if (i == (msg->len - 1)) + txd &= ~MANTIS_I2C_STOP; + + mmwrite(txd, MANTIS_I2CDATA_CTL); + if (mantis_ack_wait(mantis) < 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); + return -1; + } + udelay(500); + } + + return 0; +} + +static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) +{ + int ret = 0, i; + struct mantis_pci *mantis; + + mantis = i2c_get_adapdata(adapter); + for (i = 0; i < num; i++) { + if (msgs[i].flags & I2C_M_RD) + ret = mantis_i2c_read(mantis, &msgs[i]); + else + ret = mantis_i2c_write(mantis, &msgs[i]); + + if (ret < 0) + return ret; + } + + return num; +} + +static u32 mantis_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm mantis_algo = { + .master_xfer = mantis_i2c_xfer, + .functionality = mantis_i2c_func, +}; + +static struct i2c_adapter mantis_i2c_adapter = { + .owner = THIS_MODULE, + .name = "Mantis I2C", + .id = I2C_HW_B_MANTIS, + .class = I2C_CLASS_TV_DIGITAL, + .algo = &mantis_algo, +}; + +int __devinit mantis_i2c_init(struct mantis_pci *mantis) +{ + u32 intstat; + + memcpy(&mantis->adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); + i2c_set_adapdata(&mantis->adapter, mantis); + mantis->i2c_rc = i2c_add_adapter(&mantis->adapter); + if (mantis->i2c_rc < 0) + return mantis->i2c_rc; + + dprintk(verbose, MANTIS_DEBUG, 1, "Initializing I2C .."); + + // Clear all interrupts + intstat = mmread(MANTIS_INT_STAT); + mmwrite(intstat, MANTIS_INT_STAT); + + mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_I2CDONE, + MANTIS_INT_MASK); + + dprintk(verbose, MANTIS_DEBUG, 1, "[0x%08x/%08x]", + mmread(MANTIS_INT_STAT), mmread(MANTIS_INT_MASK)); + + return 0; +} + +int __devexit mantis_i2c_exit(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Removing I2C adapter"); + return i2c_del_adapter(&mantis->adapter); +} diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h new file mode 100644 index 00000000000..1b54e09fd86 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -0,0 +1,109 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_REG_H +#define __MANTIS_REG_H + +// Interrupts +#define MANTIS_INT_STAT 0x00 +#define MANTIS_INT_MASK 0x04 + +#define MANTIS_INT_RISCSTAT (0x0f << 28) +#define MANTIS_INT_RISCEN (0x01 << 27) +#define MANTIS_INT_I2CRACK (0x01 << 26) + +//#define MANTIS_INT_GPIF (0xff << 12) + +#define MANTIS_INT_PCMCIA7 (0x01 << 19) +#define MANTIS_INT_PCMCIA6 (0x01 << 18) +#define MANTIS_INT_PCMCIA5 (0x01 << 17) +#define MANTIS_INT_PCMCIA4 (0x01 << 16) +#define MANTIS_INT_PCMCIA3 (0x01 << 15) +#define MANTIS_INT_PCMCIA2 (0x01 << 14) +#define MANTIS_INT_PCMCIA1 (0x01 << 13) +#define MANTIS_INT_PCMCIA0 (0x01 << 12) +#define MANTIS_INT_IRQ1 (0x01 << 11) +#define MANTIS_INT_IRQ0 (0x01 << 10) +#define MANTIS_INT_OCERR (0x01 << 8) +#define MANTIS_INT_PABORT (0x01 << 7) +#define MANTIS_INT_RIPERR (0x01 << 6) +#define MANTIS_INT_PPERR (0x01 << 5) +#define MANTIS_INT_FTRGT (0x01 << 3) +#define MANTIS_INT_RISCI (0x01 << 1) +#define MANTIS_INT_I2CDONE (0x01 << 0) + +// DMA +#define MANTIS_DMA_CTL 0x08 +#define MANTIS_I2C_RD (0x01 << 7) +#define MANTIS_I2C_WR (0x01 << 6) +#define MANTIS_DCAP_MODE (0x01 << 5) +#define MANTIS_FIFO_TP_4 (0x00 << 3) +#define MANTIS_FIFO_TP_8 (0x01 << 3) +#define MANTIS_FIFO_TP_16 (0x02 << 3) +#define MANTIS_FIFO_EN (0x01 << 2) +#define MANTIS_DCAP_EN (0x01 << 1) +#define MANTIS_RISC_EN (0x01 << 0) + +#define MANTIS_RISC_START 0x10 +#define MANTIS_RISC_PC 0x14 + +// I2C +#define MANTIS_I2CDATA_CTL 0x18 +#define MANTIS_I2C_RATE_1 (0x00 << 6) +#define MANTIS_I2C_RATE_2 (0x01 << 6) +#define MANTIS_I2C_RATE_3 (0x02 << 6) +#define MANTIS_I2C_RATE_4 (0x03 << 6) +#define MANTIS_I2C_STOP (0x01 << 5) +#define MANTIS_I2C_PGMODE (0x01 << 3) + +#define MANTIS_GPIF_IRQCFG 0x98 +#define MANTIS_GPIF_IRQPOL (0x01 << 8) +#define MANTIS_MASK_WRACK (0x01 << 7) +#define MANTIS_MASK_BRRDY (0x01 << 6) +#define MANTIS_MASK_OVFLW (0x01 << 5) +#define MANTIS_MASK_OTHERR (0x01 << 4) +#define MANTIS_MASK_WSTO (0x01 << 3) +#define MANTIS_MASK_EXTIRQ (0x01 << 2) +#define MANTIS_MASK_PLUGIN (0x01 << 1) +#define MANTIS_MASK_PLUGOUT (0x01 << 0) + +#define MANTIS_GPIF_STATUS 0x9c +#define MANTIS_SBUF_KILLOP (0x01 << 15) +#define MANTIS_SBUF_OPDONE (0x01 << 14) +#define MANTIS_SBUF_EMPTY (0x01 << 13) +#define MANTIS_GPIF_DETSTAT (0x01 << 9) +#define MANTIS_GPIF_INTSTAT (0x01 << 8) +#define MANTIS_GPIF_WRACK (0x01 << 7) +#define MANTIS_GPIF_BRRDY (0x01 << 6) +#define MANTIS_SBUF_OVFLW (0x01 << 5) +#define MANTIS_GPIF_OTHERR (0x01 << 4) +#define MANTIS_SBUF_WSTO (0x01 << 3) +#define MANTIS_GPIF_EXTIRQ (0x01 << 2) +#define MANTIS_CARD_PLUGIN (0x01 << 1) +#define MANTIS_CARD_PLUGOUT (0x01 << 0) + +#define MANTIS_GPIF_ADDR 0xb0 +#define MANTIS_GPIF_RDWRN (0x01 << 31) + +#define MANTIS_GPIF_DOUT 0xb4 +#define MANTIS_GPIF_DIN 0xb8 + + +#endif //__MANTIS_REG_H diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c new file mode 100644 index 00000000000..720f4fb7e92 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -0,0 +1,151 @@ +/* + Mantis VP-1033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp1033.h" + +u8 lgtdqcs001f_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x2a, + 0x05, 0x85, + 0x06, 0x02, + 0x07, 0x00, + 0x08, 0x00, + 0x0c, 0x01, + 0x0d, 0x81, + 0x0e, 0x44, + 0x0f, 0x94, + 0x10, 0x3c, + 0x11, 0x84, + 0x12, 0xb9, + 0x13, 0xb5, + 0x14, 0x4f, + 0x15, 0xc9, + 0x16, 0x80, + 0x17, 0x36, + 0x18, 0xfb, + 0x19, 0xcf, + 0x1a, 0xbc, + 0x1c, 0x2b, + 0x1d, 0x27, + 0x1e, 0x00, + 0x1f, 0x0b, + 0x20, 0xa1, + 0x21, 0x60, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, + 0x29, 0x28, + 0x2a, 0x14, + 0x2b, 0x0f, + 0x2c, 0x09, + 0x2d, 0x05, + 0x31, 0x1f, + 0x32, 0x19, + 0x33, 0xfc, + 0x34, 0x13, + 0xff, 0xff, +}; + +struct stv0299_config lgtdqcs001f_config = { + .demod_address = 0x68, + .inittab = lgtdqcs001f_inittab, + .mclk = 88000000UL, +// .invert = 0, + .invert = 1, +// .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_0, + .volt13_op0_op1 = STV0299_VOLT13_OP0, + .min_delay_ms = 100, + .set_symbol_rate = lgtdqcs001f_set_symbol_rate, +// .pll_set = lgtdqcs001f_pll_set, +}; + +int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + u8 buf[4]; + u32 div; + + struct mantis_pci *mantis = fe->dvb->priv; + + struct i2c_msg msg = { + .addr = 0x61, + .flags = 0, + .buf = buf, + .len = sizeof (buf) + }; + div = params->frequency / 250; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x83; + buf[3] = 0xc0; + + if (params->frequency < 1531000) + buf[3] |= 0x04; + else + buf[3] &= ~0x04; + if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Write: I2C Transfer failed"); + return -EIO; + } + msleep_interruptible(100); + + return 0; +} + +int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, + u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { + aclk = 0xb7; + bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; + bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; + bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; + bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; + bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; + bclk = 0x51; + } + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/dvb/mantis/mantis_vp1033.h new file mode 100644 index 00000000000..d50f09233ff --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1033.h @@ -0,0 +1,35 @@ +/* + Mantis VP-1033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP1033_H +#define __MANTIS_VP1033_H + +#include "stv0299.h" +#include "dvb_frontend.h" + +extern struct stv0299_config lgtdqcs001f_config; + +extern int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params); + +extern int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio); + + +#endif // __MANTIS_VP1033_H diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c new file mode 100644 index 00000000000..b85ac29691d --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -0,0 +1,52 @@ +/* + Mantis VP-1034 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp1034.h" + +struct mb86a16_config vp1034_config = { + .demod_address = 0x08, + .set_voltage = vp1034_set_voltage, +}; + +int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct mantis_pci *mantis = fe->dvb->priv; + + switch (voltage) { + case SEC_VOLTAGE_13: + mmwrite((mmread(MANTIS_GPIF_ADDR)) | voltage, MANTIS_GPIF_ADDR); + dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[13V]"); + break; + case SEC_VOLTAGE_18: + mmwrite((mmread(MANTIS_GPIF_ADDR)) & voltage, MANTIS_GPIF_ADDR); + dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[18V]"); + break; + case SEC_VOLTAGE_OFF: + dprintk(verbose, MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); + break; + default: + dprintk(verbose, MANTIS_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); + return -EINVAL; + } + mmwrite(0x00, MANTIS_GPIF_DOUT); + + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/dvb/mantis/mantis_vp1034.h new file mode 100644 index 00000000000..2324dada09d --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1034.h @@ -0,0 +1,30 @@ +/* + Mantis VP-1034 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP1034_H +#define __MANTIS_VP1034_H + +#include "mb86a16.h" +#include "dvb_frontend.h" + +extern struct mb86a16_config vp1034_config; +extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage); + +#endif // __MANTIS_VP1034_H diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c new file mode 100644 index 00000000000..bca9ebaf39d --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -0,0 +1,73 @@ +/* + Mantis VP-2033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp2033.h" + +struct tda10021_state { + struct i2c_adapter *i2c; + struct dvb_frontend_ops ops; + /* configuration settings */ + const struct tda10021_config *config; + struct dvb_frontend frontend; + + u8 pwm; + u8 reg0; +}; + +struct cu1216_config philips_cu1216_config = { + .demod_address = 0x18 >> 1, + .pll_set = philips_cu1216_tuner_set, +// .fe_reset = mantis_fe_reset, +}; + +int philips_cu1216_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ +// struct tda10021_state *state = fe->demodulator_priv; + struct mantis_pci *mantis = fe->dvb->priv; + + u8 buf[4]; + + struct i2c_msg msg = { + .addr = 0xc0 >> 1, + .flags = 0, + .buf = buf, + .len = sizeof (buf) + }; + +#define TUNER_MUL 62500 + + u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x86; + buf[3] = (params->frequency < 150000000 ? 0xA1 : + params->frequency < 445000000 ? 0x92 : 0x34); + +// if (i2c_transfer(state->i2c, &msg, 1) < 0) { + if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { + printk("%s tuner not ack!\n", __FUNCTION__); + return -EIO; + } + msleep(100); + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h new file mode 100644 index 00000000000..29baba18096 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -0,0 +1,33 @@ +/* + Mantis VP-2033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP2033_H +#define __MANTIS_VP2033_H + +#include "cu1216.h" +#include "dvb_frontend.h" + +extern struct cu1216_config philips_cu1216_config; + +extern int philips_cu1216_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params); + + +#endif // __MANTIS_VP2033_H diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c new file mode 100644 index 00000000000..f44f226ce9a --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -0,0 +1,53 @@ +/* + Mantis VP-3030 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp3030.h" + +struct zl10353_config mantis_vp3030_config = { + .demod_address = 0x0f, +}; + +int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + u8 buf[4]; + int rc; + struct mantis_pci *mantis = fe->dvb->priv; + + struct i2c_msg tuner_msg = { + .addr = 0x60, + .flags = 0, + .buf = buf, + .len = sizeof (buf) + }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + rc = i2c_transfer(&mantis->adapter, &tuner_msg, 1); + if (rc != 1) { + printk("%s: I2C Transfer returned [%d]\n", __func__, rc); + return -EIO; + } + msleep_interruptible(1); + printk("%s: Send params to tuner ok!!!\n", __func__); + + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/dvb/mantis/mantis_vp3030.h new file mode 100644 index 00000000000..f8e72cce7e6 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3030.h @@ -0,0 +1,30 @@ +/* + Mantis VP-3030 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP3030_H +#define __MANTIS_VP3030_H + +#include "zl10353.h" +#include "dvb-pll.h" +#include "dvb_frontend.h" + +extern struct zl10353_config mantis_vp3030_config; + +#endif // __MANTIS_VP3030_H -- cgit v1.2.3-70-g09d2 From a890cce595c86013ca1fba644c25c01b86149b23 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 21:58:38 -0300 Subject: V4L/DVB (13700): [MB86A16] Need a bit of settling time Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 6a78a0c7403..e8fa90801d7 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -243,11 +243,16 @@ static int initial_set(struct mb86a16_state *state) { if (stlp_set(state, 5, 7)) goto err; + + udelay(100); if (afcex_data_set(state, 0, 0)) goto err; + + udelay(100); if (afcofs_data_set(state, 0, 0)) goto err; + udelay(100); if (mb86a16_write(state, MB86A16_CRLFILTCOEF1, 0x16) < 0) goto err; if (mb86a16_write(state, 0x2f, 0x21) < 0) @@ -1149,11 +1154,12 @@ static int mb86a16_set_fe(struct mb86a16_state *state) v, R, swp_ofs, &fOSC, &afcex_freq, &AFCEX_L, &AFCEX_H); + udelay(100); if (rf_val_set(state, fOSC, state->srate, R) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); return -1; } - + udelay(100); if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); return -1; -- cgit v1.2.3-70-g09d2 From b05c90de08b582172b8f63dd751ac0a1aee421e9 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 21:59:20 -0300 Subject: V4L/DVB (13701): [MB86A16] Reduce Carrier Recovery range to 3Mhz Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index e8fa90801d7..47c0d5739dd 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1036,8 +1036,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) dprintk(verbose, MB86A16_INFO, 1, "freq=%d Mhz, symbrt=%d Ksps", state->frequency, state->srate); - fcp = 5000; // (carrier recovery [kHz]) -// fcp = 3000; + fcp = 3000; swp_ofs = state->srate / 4; for (i = 0; i < 60; i++) -- cgit v1.2.3-70-g09d2 From e15c7ccd31faa0618478ad78e11423891919a87e Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:00:50 -0300 Subject: V4L/DVB (13702): [MB86A16] need to wait a bit more than the computed time for a Factor of safety Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 47c0d5739dd..ad03b110f73 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -417,7 +417,8 @@ static int signal_det(struct mb86a16_state *state, int ret ; int smrtd ; int wait_sym ; - int wait_t ; + + u32 wait_t; unsigned char S[3] ; int i ; @@ -1429,6 +1430,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2; wait_t = 7 + (2097152 + state->srate / 2) / state->srate; } + wait_t *= 2; /* FOS */ S2T_set(state, S2T); S45T_set(state, S4T, S5T); Vi_set(state, ETH, VIA); -- cgit v1.2.3-70-g09d2 From 776c3ebe9678f86b9b0e72d541208bb39f9551c6 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:01:39 -0300 Subject: V4L/DVB (13703): [MB86A16] Fix wrong message printed out Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index ad03b110f73..82b12714461 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1475,7 +1475,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) SEQ_set(state, 1); } } else { - dprintk(verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); + dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC"); SEQ_set(state, 1); } } -- cgit v1.2.3-70-g09d2 From 071e3060a5f482e5948608d55e28bc7f5dd759cd Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:02:19 -0300 Subject: V4L/DVB (13704): [MB86A16] FIX: Don't loop again, if we have SYNC Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 82b12714461..361e4762346 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1487,6 +1487,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) if (sync) { dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******"); freqerr_chk(state, state->frequency, state->srate, 1); + break; } } -- cgit v1.2.3-70-g09d2 From bd1fcac0148fb4a44395227edb0ff8ee31e09de1 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:06:15 -0300 Subject: V4L/DVB (13705): [Mantis] FIX: Do not return IRQ_HANDLED in the unlikely case Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 328 ++++++++++++++++++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_pci.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c new file mode 100644 index 00000000000..68ff1b2a0b3 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -0,0 +1,328 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "mantis_common.h" +#include "mantis_core.h" + +#include +#include +#include +#include + +unsigned int verbose = 1; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); + +unsigned int devs; + +#define PCI_VENDOR_ID_MANTIS 0x1822 +#define PCI_DEVICE_ID_MANTIS_R11 0x4e35 +#define DRIVER_NAME "Mantis" + +static struct pci_device_id mantis_pci_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MANTIS, PCI_DEVICE_ID_MANTIS_R11) }, + { 0 }, +}; + +MODULE_DEVICE_TABLE(pci, mantis_pci_table); + +static irqreturn_t mantis_pci_irq(int irq, void *dev_id) +{ + int i = 0, interrupts = 0; + u32 stat = 0, mask = 0, lstat = 0, mstat = 0; + struct mantis_pci *mantis; + + mantis = (struct mantis_pci *) dev_id; + if (unlikely(mantis == NULL)) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis == NULL"); + return IRQ_NONE; + } + stat = mmread(MANTIS_INT_STAT); + mask = mmread(MANTIS_INT_MASK); + mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; + + if (!(stat & mask)) { + dprintk(verbose, MANTIS_DEBUG, 1, "Not ours !"); + return IRQ_NONE; + } + mmwrite(lstat, MANTIS_INT_STAT); + interrupts = hweight32(stat); + dprintk(verbose, MANTIS_DEBUG, 0, "=== Interrupts[%04x/%04x]=%d [", stat, mask, interrupts); + + while (lstat) { + if (lstat & MANTIS_INT_RISCEN) { + dprintk(verbose, MANTIS_DEBUG, 0, "* DMA enabl *"); + lstat &= ~MANTIS_INT_RISCEN; + + } else if (lstat & MANTIS_INT_I2CRACK) { + dprintk(verbose, MANTIS_DEBUG, 0, "* I2C R-ACK *"); + mantis->mantis_int_stat = stat; + mantis->mantis_int_mask = mask; + wake_up(&mantis->i2c_wq); + lstat &= ~MANTIS_INT_I2CRACK; + + } else if (lstat & MANTIS_INT_PCMCIA7) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-07 *"); + lstat &= ~MANTIS_INT_PCMCIA7; + + } else if (lstat & MANTIS_INT_PCMCIA6) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-06 *"); + lstat &= ~MANTIS_INT_PCMCIA6; + + } else if (lstat & MANTIS_INT_PCMCIA5) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-05 *"); + lstat &= ~MANTIS_INT_PCMCIA5; + + } else if (lstat & MANTIS_INT_PCMCIA4) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-04 *"); + lstat &= ~MANTIS_INT_PCMCIA4; + + } else if (lstat & MANTIS_INT_PCMCIA3) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-03 *"); + lstat &= ~MANTIS_INT_PCMCIA3; + + } else if (lstat & MANTIS_INT_PCMCIA2) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-02 *"); + lstat &= ~MANTIS_INT_PCMCIA2; + + } else if (lstat & MANTIS_INT_PCMCIA1) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-01 *"); + lstat &= ~MANTIS_INT_PCMCIA1; + + } else if (lstat & MANTIS_INT_PCMCIA0) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-00 *"); + lstat &= ~MANTIS_INT_PCMCIA0; + + } else if (lstat & MANTIS_INT_IRQ0) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); + lstat &= ~MANTIS_INT_IRQ0; + + } else if (lstat & MANTIS_INT_IRQ1) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); + lstat &= ~MANTIS_INT_IRQ1; + + } else if (lstat & MANTIS_INT_OCERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT OCERR *"); + lstat &= ~MANTIS_INT_OCERR; + + } else if (lstat & MANTIS_INT_PABORT) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT PABRT *"); + lstat &= ~MANTIS_INT_PABORT; + + } else if (lstat & MANTIS_INT_RIPERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT RIPRR *"); + lstat &= ~MANTIS_INT_RIPERR; + + } else if (lstat & MANTIS_INT_PPERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT PPERR *"); + lstat &= ~MANTIS_INT_PPERR; + + } else if (lstat & MANTIS_INT_FTRGT) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT FTRGT *"); + lstat &= ~MANTIS_INT_FTRGT; + + } else if (lstat & MANTIS_INT_RISCI) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT RISCI *"); + mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; + tasklet_schedule(&mantis->tasklet); + lstat &= ~MANTIS_INT_RISCI; + + } else if (lstat & MANTIS_INT_I2CDONE) { + dprintk(verbose, MANTIS_DEBUG, 0, "* I2C DONE *"); + mantis->mantis_int_stat = stat; + mantis->mantis_int_mask = mask; + lstat &= ~MANTIS_INT_I2CDONE; + } else { + dprintk(verbose, MANTIS_DEBUG, 0, + "* Unknown [%04x/%04x] *", stat, mask); + break; + } + i++; + if (i > interrupts) { + dprintk(verbose, MANTIS_ERROR, 1, "going Loopy ! -- BREAK --"); + break; + } + } + dprintk(verbose, MANTIS_DEBUG, 0, "] ===\n"); + + return IRQ_HANDLED; +} + + +static int __devinit mantis_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *mantis_pci_table) +{ + u8 revision, latency; + struct mantis_pci *mantis; + int ret = 0; + + devs++; + + mantis = kmalloc(sizeof (struct mantis_pci), GFP_KERNEL); + if (mantis == NULL) { + printk("%s: Out of memory\n", __func__); + ret = -ENOMEM; + goto err; + } + memset(mantis, 0, sizeof (struct mantis_pci)); + mantis->num = devs; + if (pci_enable_device(pdev)) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis PCI enable failed"); + ret = -ENODEV; + goto err; + } + mantis->mantis_addr = pci_resource_start(pdev, 0); + if (!request_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0), DRIVER_NAME)) { + ret = -ENODEV; + goto err0; + } + + if ((mantis->mantis_mmio = ioremap(mantis->mantis_addr, 0x1000)) == NULL) { + dprintk(verbose, MANTIS_ERROR, 1, "IO remap failed"); + ret = -ENODEV; + goto err1; + } + + // Clear and disable all interrupts at startup + // to avoid lockup situations + mmwrite(0x00, MANTIS_INT_MASK); + if (request_irq(pdev->irq, mantis_pci_irq, IRQF_SHARED | IRQF_DISABLED, + DRIVER_NAME, mantis) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, "Mantis IRQ reg failed"); + ret = -ENODEV; + goto err2; + } + pci_set_master(pdev); + pci_set_drvdata(pdev, mantis); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + mantis->latency = latency; + mantis->revision = revision; + mantis->pdev = pdev; + init_waitqueue_head(&mantis->i2c_wq); + + // CAM bypass + //mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ1, MANTIS_INT_MASK); + dprintk(verbose, MANTIS_INFO, 1, "gpif status: %04x irqcfg: %04x", mmread(0x9c), mmread(0x98)); + if ((mmread(0x9c) & 0x200) != 0) { //CAM inserted + msleep_interruptible(1); + if ((mmread(0x9c) & 0x200) != 0) + mmwrite(((mmread(0x98) | 0x01) & ~0x02), 0x98); + else + mmwrite(((mmread(0x98) | 0x02) & ~0x01), 0x98); + + } else { + mmwrite(((mmread(0x98) | 0x02) & ~0x01), 0x98); + } + mantis_set_direction(mantis, 0); + + // default latency if none specified + if (!latency) + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 32); + dprintk(verbose, MANTIS_ERROR, 0, "Mantis Rev %d, ", + mantis->revision); + + dprintk(verbose, MANTIS_ERROR, 0, + "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", + pdev->irq, mantis->latency, + mantis->mantis_addr, mantis->mantis_mmio); + + // No more PCI specific stuff ! + if (mantis_core_init(mantis) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis core init failed"); + ret = -ENODEV; + goto err2; + } + + return 0; + + // Error conditions .. +err2: + dprintk(verbose, MANTIS_DEBUG, 1, "Err: IO Unmap"); + if (mantis->mantis_mmio) + iounmap(mantis->mantis_mmio); +err1: + dprintk(verbose, MANTIS_DEBUG, 1, "Err: Release regions"); + release_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + pci_disable_device(pdev); +err0: + dprintk(verbose, MANTIS_DEBUG, 1, "Err: Free"); + kfree(mantis); +err: + dprintk(verbose, MANTIS_DEBUG, 1, "Err:"); + return ret; +} + +static void __devexit mantis_pci_remove(struct pci_dev *pdev) +{ + struct mantis_pci *mantis = pci_get_drvdata(pdev); + + if (mantis == NULL) { + dprintk(verbose, MANTIS_ERROR, 1, "Aeio, Mantis NULL ptr"); + return; + } + mantis_core_exit(mantis); + dprintk(verbose, MANTIS_ERROR, 1, "Removing -->Mantis irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p", + pdev->irq, mantis->latency, mantis->mantis_addr, + mantis->mantis_mmio); + + free_irq(pdev->irq, mantis); + pci_release_regions(pdev); + if (mantis_dma_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); + + pci_set_drvdata(pdev, NULL); + pci_disable_device(pdev); + kfree(mantis); +} + +static struct pci_driver mantis_pci_driver = { + .name = DRIVER_NAME, + .id_table = mantis_pci_table, + .probe = mantis_pci_probe, + .remove = mantis_pci_remove, +}; + +static int __devinit mantis_pci_init(void) +{ + return pci_register_driver(&mantis_pci_driver); +} + +static void __devexit mantis_pci_exit(void) +{ + pci_unregister_driver(&mantis_pci_driver); +} + +module_init(mantis_pci_init); +module_exit(mantis_pci_exit); + +MODULE_DESCRIPTION("Mantis PCI DTV bridge driver"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-70-g09d2 From df0cca174b4d85ea041509a13e5e68b377758bf1 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:07:24 -0300 Subject: V4L/DVB (13706): [MB86A16] Overhaul * better ISR handling * I2C fixes * better handling of configurations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 14 ++- drivers/media/dvb/mantis/mantis_core.c | 95 +++++++++-------- drivers/media/dvb/mantis/mantis_dvb.c | 13 +-- drivers/media/dvb/mantis/mantis_i2c.c | 68 ++++++------- drivers/media/dvb/mantis/mantis_pci.c | 170 ++++++++++++------------------- drivers/media/dvb/mantis/mantis_vp1033.c | 8 ++ drivers/media/dvb/mantis/mantis_vp1033.h | 6 +- drivers/media/dvb/mantis/mantis_vp1034.c | 8 ++ drivers/media/dvb/mantis/mantis_vp1034.h | 7 +- drivers/media/dvb/mantis/mantis_vp2033.c | 20 ++-- drivers/media/dvb/mantis/mantis_vp2033.h | 6 +- drivers/media/dvb/mantis/mantis_vp3030.c | 10 +- drivers/media/dvb/mantis/mantis_vp3030.h | 8 +- 13 files changed, 215 insertions(+), 218 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index ba360f88496..60a7457b2b9 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -65,10 +65,19 @@ #define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr) +struct mantis_hwconfig { + char *model_name; + char *dev_type; +}; + + struct mantis_pci { /* PCI stuff */ u16 vendor_id; u16 device_id; + u16 subsystem_vendor; + u16 subsystem_device; + u8 latency; struct pci_dev *pdev; @@ -110,7 +119,7 @@ struct mantis_pci { u8 feeds; - struct mantis_config *config; + struct mantis_hwconfig *hwconfig; u32 mantis_int_stat; u32 mantis_int_mask; @@ -121,7 +130,8 @@ struct mantis_pci { u32 sub_device_id; /* A12 A13 A14 */ - int gpio_status;}; + int gpio_status; +}; extern unsigned int verbose; extern unsigned int devs; diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 11122775245..1012959499a 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -20,7 +20,10 @@ #include "mantis_common.h" #include "mantis_core.h" - +#include "mantis_vp1033.h" +#include "mantis_vp1034.h" +#include "mantis_vp2033.h" +#include "mantis_vp3030.h" static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) { @@ -45,7 +48,7 @@ static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) return err; } - msleep_interruptible(2); +// msleep_interruptible(2); return 0; } @@ -72,41 +75,6 @@ static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) return 0; } -static int get_subdevice_id(struct mantis_pci *mantis) -{ - int err; - static u8 sub_device_id[2]; - - mantis->sub_device_id = 0; - sub_device_id[0] = 0xfc; - if ((err = read_eeprom_byte(mantis, &sub_device_id[0], 2)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); - return err; - } - mantis->sub_device_id = (sub_device_id[0] << 8) | sub_device_id[1]; - dprintk(verbose, MANTIS_ERROR, 1, "Sub Device ID=[0x%04x]", - mantis->sub_device_id); - - return 0; -} - -static int get_subvendor_id(struct mantis_pci *mantis) -{ - int err; - static u8 sub_vendor_id[2]; - - mantis->sub_vendor_id = 0; - sub_vendor_id[0] = 0xfe; - if ((err = read_eeprom_byte(mantis, &sub_vendor_id[0], 2)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); - return err; - } - mantis->sub_vendor_id = (sub_vendor_id[0] << 8) | sub_vendor_id[1]; - dprintk(verbose, MANTIS_ERROR, 1, "Sub Vendor ID=[0x%04x]", - mantis->sub_vendor_id); - - return 0; -} static int get_mac_address(struct mantis_pci *mantis) { @@ -118,8 +86,8 @@ static int get_mac_address(struct mantis_pci *mantis) return err; } - dprintk(verbose, MANTIS_ERROR, 1, - "MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]", + dprintk(verbose, MANTIS_ERROR, 0, + " MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n", mantis->mac_address[0], mantis->mac_address[1], mantis->mac_address[2], mantis->mac_address[3], mantis->mac_address[4], mantis->mac_address[5]); @@ -127,11 +95,51 @@ static int get_mac_address(struct mantis_pci *mantis) return 0; } +#define MANTIS_MODEL_UNKNOWN "UNKNOWN" +#define MANTIS_DEV_UNKNOWN "UNKNOWN" + +struct mantis_hwconfig unknown_device = { + .model_name = MANTIS_MODEL_UNKNOWN, + .dev_type = MANTIS_DEV_UNKNOWN, +}; + +static void mantis_load_config(struct mantis_pci *mantis) +{ + switch (mantis->subsystem_device) { + case MANTIS_VP_1033_DVB_S: // VP-1033 + mantis->hwconfig = &vp1033_mantis_config; + break; + case MANTIS_VP_1034_DVB_S: // VP-1034 + mantis->hwconfig = &vp1034_mantis_config; + break; + case MANTIS_VP_2033_DVB_C: // VP-2033 + mantis->hwconfig = &vp2033_mantis_config; + break; + case MANTIS_VP_3030_DVB_T: // VP-3030 + mantis->hwconfig = &vp3030_mantis_config; + break; + default: + mantis->hwconfig = &unknown_device; + break; + } +} int mantis_core_init(struct mantis_pci *mantis) { int err = 0; + mantis_load_config(mantis); + dprintk(verbose, MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n", + mantis->hwconfig->model_name, mantis->hwconfig->dev_type, + mantis->pdev->bus->number, PCI_SLOT(mantis->pdev->devfn), PCI_FUNC(mantis->pdev->devfn)); + dprintk(verbose, MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", + mantis->revision, + mantis->subsystem_vendor, mantis->subsystem_device); + dprintk(verbose, MANTIS_ERROR, 0, + "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", + mantis->pdev->irq, mantis->latency, + mantis->mantis_addr, mantis->mantis_mmio); + if ((err = mantis_i2c_init(mantis)) < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed"); return err; @@ -140,14 +148,6 @@ int mantis_core_init(struct mantis_pci *mantis) dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed"); return err; } - if ((err = get_subvendor_id(mantis)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "get Sub vendor ID failed"); - return err; - } - if ((err = get_subdevice_id(mantis)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "get Sub device ID failed"); - return err; - } if ((err = mantis_dma_init(mantis)) < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed"); return err; @@ -162,7 +162,6 @@ int mantis_core_init(struct mantis_pci *mantis) int mantis_core_exit(struct mantis_pci *mantis) { - mantis_dma_stop(mantis); dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping"); if (mantis_dma_exit(mantis) < 0) diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 5830d4a7bda..319bb8bef4e 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -206,22 +206,13 @@ err0: return result; } -#define MANTIS_VP_1027_DVB_S 0x0013 -#define MANTIS_VP_1033_DVB_S 0x0016 -#define MANTIS_VP_1034_DVB_S 0x0014 -#define MANTIS_VP_1040_DVB_S2 -#define MANTIS_VP_1041_DVB_S2 -#define MANTIS_VP_2033_DVB_C 0x0008 -#define MANTIS_VP_3024_DVB_T 0x0009 -#define MANTIS_VP_3030_DVB_T 0x0024 - int __devinit mantis_frontend_init(struct mantis_pci *mantis) { dprintk(verbose, MANTIS_DEBUG, 1, "Mantis frontend Init"); mantis_fe_powerup(mantis); mantis_frontend_reset(mantis); - dprintk(verbose, MANTIS_DEBUG, 1, "Device ID=%02x", mantis->sub_device_id); - switch (mantis->sub_device_id) { + dprintk(verbose, MANTIS_DEBUG, 1, "Device ID=%02x", mantis->subsystem_device); + switch (mantis->subsystem_device) { case MANTIS_VP_1033_DVB_S: // VP-1033 dprintk(verbose, MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); mantis->fe = stv0299_attach(&lgtdqcs001f_config, diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index cfecb344bb7..8b90a2af687 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -33,32 +33,27 @@ static int mantis_ack_wait(struct mantis_pci *mantis) { int rc = 0; + u32 timeout = 0; if (wait_event_interruptible_timeout(mantis->i2c_wq, - mantis->mantis_int_stat & MANTIS_INT_I2CRACK, - msecs_to_jiffies(50)) == -ERESTARTSYS) + mantis->mantis_int_stat & MANTIS_INT_I2CDONE, + msecs_to_jiffies(50)) == -ERESTARTSYS) { + dprintk(verbose, MANTIS_DEBUG, 1, "I2C Transfer failed, Master !I2CDONE"); rc = -EREMOTEIO; -/* - // Wait till we are done - while (mantis->mantis_int_stat & MANTIS_INT_I2CRACK){ - if (mantis->mantis_int_stat & MANTIS_INT_I2CDONE) { - mantis->mantis_int_stat &= ~MANTIS_INT_I2CRACK; -// dprintk(verbose, MANTIS_DEBUG, 1, "SLAVE RACK 'ed .. Waiting for I2CDONE"); + } + while (!(mantis->mantis_int_stat & MANTIS_INT_I2CRACK)) { + dprintk(verbose, MANTIS_DEBUG, 1, "Waiting for Slave RACK"); + mantis->mantis_int_stat = mmread(MANTIS_INT_STAT); + msleep(5); + timeout++; + if (timeout > 500) { + dprintk(verbose, MANTIS_ERROR, 1, "Slave RACK Fail !"); + rc = -EREMOTEIO; break; } } - - if (mantis->mantis_int_stat & MANTIS_INT_I2CDONE) { -// dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Int I2CDONE"); - rc = 1; - } - - mantis->mantis_int_stat &= ~MANTIS_INT_I2CDONE; -*/ - // .. - if (mantis->mantis_int_stat & MANTIS_INT_I2CRACK) - msleep_interruptible(10); + udelay(350); return rc; } @@ -67,7 +62,7 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) { u32 rxd, i; - dprintk(verbose, MANTIS_DEBUG, 1, "Address=[0x%02x]", msg->addr); + dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); for (i = 0; i < msg->len; i++) { rxd = (msg->addr << 25) | (1 << 24) | MANTIS_I2C_RATE_3 @@ -77,18 +72,17 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) if (i == (msg->len - 1)) rxd &= ~MANTIS_I2C_STOP; + mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(rxd, MANTIS_I2CDATA_CTL); - if (mantis_ack_wait(mantis) < 0) { + if (mantis_ack_wait(mantis) != 0) { dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); - return -EIO; + return -EREMOTEIO; } rxd = mmread(MANTIS_I2CDATA_CTL); msg->buf[i] = (u8)((rxd >> 8) & 0xFF); - dprintk(verbose, MANTIS_DEBUG, 1, - "Data=[0x%02x]", i, msg->buf[i]); - - msleep_interruptible(2); + dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); } + dprintk(verbose, MANTIS_INFO, 0, "]\n"); return 0; } @@ -98,9 +92,9 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg int i; u32 txd = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "Address=[0x%02x]", msg->addr); + dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); for (i = 0; i < msg->len; i++) { - dprintk(verbose, MANTIS_DEBUG, 1, "Data=[0x%02x]", i, msg->buf[i]); + dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); txd = (msg->addr << 25) | (msg->buf[i] << 8) | MANTIS_I2C_RATE_3 | MANTIS_I2C_STOP @@ -109,13 +103,14 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg if (i == (msg->len - 1)) txd &= ~MANTIS_I2C_STOP; + mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(txd, MANTIS_I2CDATA_CTL); - if (mantis_ack_wait(mantis) < 0) { + if (mantis_ack_wait(mantis) != 0) { dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); - return -1; + return -EREMOTEIO; } - udelay(500); } + dprintk(verbose, MANTIS_INFO, 0, "]\n"); return 0; } @@ -159,7 +154,7 @@ static struct i2c_adapter mantis_i2c_adapter = { int __devinit mantis_i2c_init(struct mantis_pci *mantis) { - u32 intstat; + u32 intstat, intmask; memcpy(&mantis->adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); i2c_set_adapdata(&mantis->adapter, mantis); @@ -169,15 +164,12 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) dprintk(verbose, MANTIS_DEBUG, 1, "Initializing I2C .."); - // Clear all interrupts intstat = mmread(MANTIS_INT_STAT); + intmask = mmread(MANTIS_INT_MASK); mmwrite(intstat, MANTIS_INT_STAT); + mmwrite(intmask | MANTIS_INT_I2CDONE, MANTIS_INT_MASK); - mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_I2CDONE, - MANTIS_INT_MASK); - - dprintk(verbose, MANTIS_DEBUG, 1, "[0x%08x/%08x]", - mmread(MANTIS_INT_STAT), mmread(MANTIS_INT_MASK)); + dprintk(verbose, MANTIS_DEBUG, 1, "[0x%08x/%08x]", intstat, intmask); return 0; } diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 68ff1b2a0b3..0bc25d2778f 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -52,7 +52,6 @@ MODULE_DEVICE_TABLE(pci, mantis_pci_table); static irqreturn_t mantis_pci_irq(int irq, void *dev_id) { - int i = 0, interrupts = 0; u32 stat = 0, mask = 0, lstat = 0, mstat = 0; struct mantis_pci *mantis; @@ -64,109 +63,67 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) stat = mmread(MANTIS_INT_STAT); mask = mmread(MANTIS_INT_MASK); mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; - - if (!(stat & mask)) { - dprintk(verbose, MANTIS_DEBUG, 1, "Not ours !"); + if (!(stat & mask)) return IRQ_NONE; + + mantis->mantis_int_stat = stat; + mantis->mantis_int_mask = mask; + dprintk(verbose, MANTIS_DEBUG, 0, "=== Interrupts[%04x/%04x]= [", stat, mask); + if (stat & MANTIS_INT_RISCEN) { + dprintk(verbose, MANTIS_DEBUG, 0, "* DMA enabl *"); + } + if (stat & MANTIS_INT_I2CRACK) { + dprintk(verbose, MANTIS_DEBUG, 0, "* I2C R-ACK *"); +// wake_up(&mantis->i2c_wq); + } + if (stat & MANTIS_INT_PCMCIA7) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-07 *"); + } + if (stat & MANTIS_INT_IRQ0) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); + } + if (stat & MANTIS_INT_IRQ1) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); + } + if (stat & MANTIS_INT_OCERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT OCERR *"); + } + if (stat & MANTIS_INT_PABORT) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT PABRT *"); + } + if (stat & MANTIS_INT_RIPERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT RIPRR *"); } - mmwrite(lstat, MANTIS_INT_STAT); - interrupts = hweight32(stat); - dprintk(verbose, MANTIS_DEBUG, 0, "=== Interrupts[%04x/%04x]=%d [", stat, mask, interrupts); - - while (lstat) { - if (lstat & MANTIS_INT_RISCEN) { - dprintk(verbose, MANTIS_DEBUG, 0, "* DMA enabl *"); - lstat &= ~MANTIS_INT_RISCEN; - - } else if (lstat & MANTIS_INT_I2CRACK) { - dprintk(verbose, MANTIS_DEBUG, 0, "* I2C R-ACK *"); - mantis->mantis_int_stat = stat; - mantis->mantis_int_mask = mask; - wake_up(&mantis->i2c_wq); - lstat &= ~MANTIS_INT_I2CRACK; - - } else if (lstat & MANTIS_INT_PCMCIA7) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-07 *"); - lstat &= ~MANTIS_INT_PCMCIA7; - - } else if (lstat & MANTIS_INT_PCMCIA6) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-06 *"); - lstat &= ~MANTIS_INT_PCMCIA6; - - } else if (lstat & MANTIS_INT_PCMCIA5) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-05 *"); - lstat &= ~MANTIS_INT_PCMCIA5; - - } else if (lstat & MANTIS_INT_PCMCIA4) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-04 *"); - lstat &= ~MANTIS_INT_PCMCIA4; - - } else if (lstat & MANTIS_INT_PCMCIA3) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-03 *"); - lstat &= ~MANTIS_INT_PCMCIA3; - - } else if (lstat & MANTIS_INT_PCMCIA2) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-02 *"); - lstat &= ~MANTIS_INT_PCMCIA2; - - } else if (lstat & MANTIS_INT_PCMCIA1) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-01 *"); - lstat &= ~MANTIS_INT_PCMCIA1; - - } else if (lstat & MANTIS_INT_PCMCIA0) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-00 *"); - lstat &= ~MANTIS_INT_PCMCIA0; - - } else if (lstat & MANTIS_INT_IRQ0) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); - lstat &= ~MANTIS_INT_IRQ0; - - } else if (lstat & MANTIS_INT_IRQ1) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); - lstat &= ~MANTIS_INT_IRQ1; - - } else if (lstat & MANTIS_INT_OCERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT OCERR *"); - lstat &= ~MANTIS_INT_OCERR; - - } else if (lstat & MANTIS_INT_PABORT) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT PABRT *"); - lstat &= ~MANTIS_INT_PABORT; - - } else if (lstat & MANTIS_INT_RIPERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT RIPRR *"); - lstat &= ~MANTIS_INT_RIPERR; - - } else if (lstat & MANTIS_INT_PPERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT PPERR *"); - lstat &= ~MANTIS_INT_PPERR; - - } else if (lstat & MANTIS_INT_FTRGT) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT FTRGT *"); - lstat &= ~MANTIS_INT_FTRGT; - - } else if (lstat & MANTIS_INT_RISCI) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT RISCI *"); - mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; - tasklet_schedule(&mantis->tasklet); - lstat &= ~MANTIS_INT_RISCI; - - } else if (lstat & MANTIS_INT_I2CDONE) { - dprintk(verbose, MANTIS_DEBUG, 0, "* I2C DONE *"); - mantis->mantis_int_stat = stat; - mantis->mantis_int_mask = mask; - lstat &= ~MANTIS_INT_I2CDONE; - } else { - dprintk(verbose, MANTIS_DEBUG, 0, - "* Unknown [%04x/%04x] *", stat, mask); - break; - } - i++; - if (i > interrupts) { - dprintk(verbose, MANTIS_ERROR, 1, "going Loopy ! -- BREAK --"); - break; - } + if (stat & MANTIS_INT_PPERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT PPERR *"); } + if (stat & MANTIS_INT_FTRGT) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT FTRGT *"); + } + if (stat & MANTIS_INT_RISCI) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT RISCI *"); + mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; + tasklet_schedule(&mantis->tasklet); + } + if (stat & MANTIS_INT_I2CDONE) { + dprintk(verbose, MANTIS_DEBUG, 0, "* I2C DONE *"); + wake_up(&mantis->i2c_wq); + } + mmwrite(stat, MANTIS_INT_STAT); + stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | + MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | + MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | + MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | + MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | + MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | + MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | + MANTIS_INT_PABORT | MANTIS_INT_RIPERR | + MANTIS_INT_PPERR | MANTIS_INT_FTRGT | + MANTIS_INT_RISCI); + + if (stat) + dprintk(verbose, MANTIS_DEBUG, 0, "* Unknown [%04x] *", stat); + dprintk(verbose, MANTIS_DEBUG, 0, "] ===\n"); return IRQ_HANDLED; @@ -180,8 +137,6 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, struct mantis_pci *mantis; int ret = 0; - devs++; - mantis = kmalloc(sizeof (struct mantis_pci), GFP_KERNEL); if (mantis == NULL) { printk("%s: Out of memory\n", __func__); @@ -190,6 +145,8 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, } memset(mantis, 0, sizeof (struct mantis_pci)); mantis->num = devs; + devs++; + if (pci_enable_device(pdev)) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis PCI enable failed"); ret = -ENODEV; @@ -225,11 +182,13 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, mantis->latency = latency; mantis->revision = revision; mantis->pdev = pdev; + mantis->subsystem_vendor = pdev->subsystem_vendor; + mantis->subsystem_device = pdev->subsystem_device; init_waitqueue_head(&mantis->i2c_wq); // CAM bypass //mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ1, MANTIS_INT_MASK); - dprintk(verbose, MANTIS_INFO, 1, "gpif status: %04x irqcfg: %04x", mmread(0x9c), mmread(0x98)); + dprintk(verbose, MANTIS_INFO, 0, "\ngpif status: %04x irqcfg: %04x\n", mmread(0x9c), mmread(0x98)); if ((mmread(0x9c) & 0x200) != 0) { //CAM inserted msleep_interruptible(1); if ((mmread(0x9c) & 0x200) != 0) @@ -242,11 +201,8 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, } mantis_set_direction(mantis, 0); - // default latency if none specified if (!latency) pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 32); - dprintk(verbose, MANTIS_ERROR, 0, "Mantis Rev %d, ", - mantis->revision); dprintk(verbose, MANTIS_ERROR, 0, "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 720f4fb7e92..07fcc45b7f6 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -81,6 +81,14 @@ struct stv0299_config lgtdqcs001f_config = { // .pll_set = lgtdqcs001f_pll_set, }; +#define MANTIS_MODEL_NAME "VP-1033" +#define MANTIS_DEV_TYPE "DVB-S/DSS" + +struct mantis_hwconfig vp1033_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, +}; + int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/dvb/mantis/mantis_vp1033.h index d50f09233ff..e24570659d5 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.h +++ b/drivers/media/dvb/mantis/mantis_vp1033.h @@ -21,10 +21,14 @@ #ifndef __MANTIS_VP1033_H #define __MANTIS_VP1033_H -#include "stv0299.h" #include "dvb_frontend.h" +#include "mantis_common.h" +#include "stv0299.h" + +#define MANTIS_VP_1033_DVB_S 0x0016 extern struct stv0299_config lgtdqcs001f_config; +extern struct mantis_hwconfig vp1033_mantis_config; extern int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params); diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index b85ac29691d..c9c94791162 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -26,6 +26,14 @@ struct mb86a16_config vp1034_config = { .set_voltage = vp1034_set_voltage, }; +#define MANTIS_MODEL_NAME "VP-1034" +#define MANTIS_DEV_TYPE "DVB-S/DSS" + +struct mantis_hwconfig vp1034_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, +}; + int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct mantis_pci *mantis = fe->dvb->priv; diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/dvb/mantis/mantis_vp1034.h index 2324dada09d..21948573b08 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.h +++ b/drivers/media/dvb/mantis/mantis_vp1034.h @@ -21,9 +21,14 @@ #ifndef __MANTIS_VP1034_H #define __MANTIS_VP1034_H -#include "mb86a16.h" #include "dvb_frontend.h" +#include "mantis_common.h" +#include "mb86a16.h" + + +#define MANTIS_VP_1034_DVB_S 0x0014 +extern struct mantis_hwconfig vp1034_mantis_config; extern struct mb86a16_config vp1034_config; extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage); diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index bca9ebaf39d..e9895976912 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -32,9 +32,17 @@ struct tda10021_state { u8 reg0; }; +#define MANTIS_MODEL_NAME "VP-2033" +#define MANTIS_DEV_TYPE "DVB-C" + +struct mantis_hwconfig vp2033_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, +}; + struct cu1216_config philips_cu1216_config = { - .demod_address = 0x18 >> 1, - .pll_set = philips_cu1216_tuner_set, + .demod_address = 0x18 >> 1, + .pll_set = philips_cu1216_tuner_set, // .fe_reset = mantis_fe_reset, }; @@ -47,10 +55,10 @@ int philips_cu1216_tuner_set(struct dvb_frontend *fe, u8 buf[4]; struct i2c_msg msg = { - .addr = 0xc0 >> 1, - .flags = 0, - .buf = buf, - .len = sizeof (buf) + .addr = 0xc0 >> 1, + .flags = 0, + .buf = buf, + .len = sizeof (buf) }; #define TUNER_MUL 62500 diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index 29baba18096..513c491942c 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -21,10 +21,14 @@ #ifndef __MANTIS_VP2033_H #define __MANTIS_VP2033_H -#include "cu1216.h" #include "dvb_frontend.h" +#include "mantis_common.h" +#include "cu1216.h" + +#define MANTIS_VP_2033_DVB_C 0x0008 extern struct cu1216_config philips_cu1216_config; +extern struct mantis_hwconfig vp2033_mantis_config; extern int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params); diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index f44f226ce9a..8043e5d9218 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -22,7 +22,15 @@ #include "mantis_vp3030.h" struct zl10353_config mantis_vp3030_config = { - .demod_address = 0x0f, + .demod_address = 0x0f, +}; + +#define MANTIS_MODEL_NAME "VP-3030" +#define MANTIS_DEV_TYPE "DVB-T" + +struct mantis_hwconfig vp3030_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, }; int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/dvb/mantis/mantis_vp3030.h index f8e72cce7e6..acc50a48e18 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.h +++ b/drivers/media/dvb/mantis/mantis_vp3030.h @@ -21,10 +21,14 @@ #ifndef __MANTIS_VP3030_H #define __MANTIS_VP3030_H -#include "zl10353.h" -#include "dvb-pll.h" #include "dvb_frontend.h" +#include "mantis_common.h" +#include "dvb-pll.h" +#include "zl10353.h" + +#define MANTIS_VP_3030_DVB_T 0x0024 extern struct zl10353_config mantis_vp3030_config; +extern struct mantis_hwconfig vp3030_mantis_config; #endif // __MANTIS_VP3030_H -- cgit v1.2.3-70-g09d2 From 55172773c57221c7c81e445d04f811f2f0478c3e Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:09:53 -0300 Subject: V4L/DVB (13707): [Mantis] Whitespace cleanup Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 60a7457b2b9..d39cbe0f241 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -83,7 +83,7 @@ struct mantis_pci { struct pci_dev *pdev; unsigned long mantis_addr; - volatile void __iomem *mantis_mmio; + volatile void __iomem *mantis_mmio; u8 irq; u8 revision; @@ -121,8 +121,8 @@ struct mantis_pci { struct mantis_hwconfig *hwconfig; - u32 mantis_int_stat; - u32 mantis_int_mask; + u32 mantis_int_stat; + u32 mantis_int_mask; /* board specific */ u8 mac_address[8]; -- cgit v1.2.3-70-g09d2 From da7365f46607207c8166167ba497e3cb3e02270d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:11:00 -0300 Subject: V4L/DVB (13708): [Mantis] Remove some dead code Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 2 -- drivers/media/dvb/mantis/mantis_pci.c | 1 - drivers/media/dvb/mantis/mantis_vp2033.c | 14 +------------- 3 files changed, 1 insertion(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 1012959499a..d159ad6fc32 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -48,7 +48,6 @@ static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) return err; } -// msleep_interruptible(2); return 0; } @@ -75,7 +74,6 @@ static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) return 0; } - static int get_mac_address(struct mantis_pci *mantis) { int err; diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 0bc25d2778f..402f866e12d 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -74,7 +74,6 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) } if (stat & MANTIS_INT_I2CRACK) { dprintk(verbose, MANTIS_DEBUG, 0, "* I2C R-ACK *"); -// wake_up(&mantis->i2c_wq); } if (stat & MANTIS_INT_PCMCIA7) { dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-07 *"); diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index e9895976912..853b558b928 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -21,17 +21,6 @@ #include "mantis_common.h" #include "mantis_vp2033.h" -struct tda10021_state { - struct i2c_adapter *i2c; - struct dvb_frontend_ops ops; - /* configuration settings */ - const struct tda10021_config *config; - struct dvb_frontend frontend; - - u8 pwm; - u8 reg0; -}; - #define MANTIS_MODEL_NAME "VP-2033" #define MANTIS_DEV_TYPE "DVB-C" @@ -49,7 +38,6 @@ struct cu1216_config philips_cu1216_config = { int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { -// struct tda10021_state *state = fe->demodulator_priv; struct mantis_pci *mantis = fe->dvb->priv; u8 buf[4]; @@ -71,11 +59,11 @@ int philips_cu1216_tuner_set(struct dvb_frontend *fe, buf[3] = (params->frequency < 150000000 ? 0xA1 : params->frequency < 445000000 ? 0x92 : 0x34); -// if (i2c_transfer(state->i2c, &msg, 1) < 0) { if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { printk("%s tuner not ack!\n", __FUNCTION__); return -EIO; } msleep(100); + return 0; } -- cgit v1.2.3-70-g09d2 From 715d341c59d2563940ae07b12f949555ccbe3efb Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:37:51 -0300 Subject: V4L/DVB (13709): [Mantis/VP-1034] Switch 13/18v for the VP-1034 properly Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_i2c.c | 10 +++++++--- drivers/media/dvb/mantis/mantis_vp1034.c | 6 ++++-- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 8b90a2af687..53c5f88227b 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -39,7 +39,7 @@ static int mantis_ack_wait(struct mantis_pci *mantis) mantis->mantis_int_stat & MANTIS_INT_I2CDONE, msecs_to_jiffies(50)) == -ERESTARTSYS) { - dprintk(verbose, MANTIS_DEBUG, 1, "I2C Transfer failed, Master !I2CDONE"); + dprintk(verbose, MANTIS_DEBUG, 1, "Master !I2CDONE"); rc = -EREMOTEIO; } while (!(mantis->mantis_int_stat & MANTIS_INT_I2CRACK)) { @@ -62,7 +62,9 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) { u32 rxd, i; - dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); + dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", + __func__, msg->addr); + for (i = 0; i < msg->len; i++) { rxd = (msg->addr << 25) | (1 << 24) | MANTIS_I2C_RATE_3 @@ -92,7 +94,9 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg int i; u32 txd = 0; - dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); + dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", + __func__, msg->addr); + for (i = 0; i < msg->len; i++) { dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); txd = (msg->addr << 25) | (msg->buf[i] << 8) diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index c9c94791162..f6766d0793d 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -40,12 +40,14 @@ int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) switch (voltage) { case SEC_VOLTAGE_13: - mmwrite((mmread(MANTIS_GPIF_ADDR)) | voltage, MANTIS_GPIF_ADDR); dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[13V]"); + gpio_set_bits(mantis, 13, 1); + gpio_set_bits(mantis, 14, 0); break; case SEC_VOLTAGE_18: - mmwrite((mmread(MANTIS_GPIF_ADDR)) & voltage, MANTIS_GPIF_ADDR); dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[18V]"); + gpio_set_bits(mantis, 13, 1); + gpio_set_bits(mantis, 14, 1); break; case SEC_VOLTAGE_OFF: dprintk(verbose, MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); -- cgit v1.2.3-70-g09d2 From 01a8c3eebb3c83df337f88332756f16154cecc0f Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:38:33 -0300 Subject: V4L/DVB (13710): [Mantis] FIX: Use swfilter (188/204) accordingly Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 4 +++- drivers/media/dvb/mantis/mantis_dma.c | 2 -- drivers/media/dvb/mantis/mantis_vp1033.c | 1 + drivers/media/dvb/mantis/mantis_vp1034.c | 1 + drivers/media/dvb/mantis/mantis_vp2033.c | 1 + drivers/media/dvb/mantis/mantis_vp3030.c | 1 + 6 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index d39cbe0f241..197393e700f 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -64,13 +64,15 @@ #define mmor(dat, addr) mmwrite((dat) | mmread(addr), addr) #define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr) +#define MANTIS_TS_188 0 +#define MANTIS_TS_204 1 struct mantis_hwconfig { char *model_name; char *dev_type; + u32 ts_size; }; - struct mantis_pci { /* PCI stuff */ u16 vendor_id; diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index 9e3aa5ec164..b8fd1c7cd29 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -154,8 +154,6 @@ err: return err; } - - static inline void mantis_risc_program(struct mantis_pci *mantis) { u32 buf_pos = 0; diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 07fcc45b7f6..daf02c12d29 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -87,6 +87,7 @@ struct stv0299_config lgtdqcs001f_config = { struct mantis_hwconfig vp1033_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, }; int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index f6766d0793d..a2fe9d42d1e 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -32,6 +32,7 @@ struct mb86a16_config vp1034_config = { struct mantis_hwconfig vp1034_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, }; int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 853b558b928..15772fe5828 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -27,6 +27,7 @@ struct mantis_hwconfig vp2033_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, }; struct cu1216_config philips_cu1216_config = { diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index 8043e5d9218..cab092ce230 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -31,6 +31,7 @@ struct zl10353_config mantis_vp3030_config = { struct mantis_hwconfig vp3030_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, }; int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, -- cgit v1.2.3-70-g09d2 From e4deee04ffda9b44f367a40dbad8306ab88cb321 Mon Sep 17 00:00:00 2001 From: Marko Ristola Date: Thu, 3 Dec 2009 05:39:22 -0300 Subject: V4L/DVB (13711): [Mantis] FIX: Do nor toggle GPIF status Signed-off-by: Marko Ristola Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dma.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index b8fd1c7cd29..e207870fb45 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -190,7 +190,8 @@ void mantis_dma_start(struct mantis_pci *mantis) mantis_risc_program(mantis); mmwrite(cpu_to_le32(mantis->risc_dma), MANTIS_RISC_START); - mmwrite(MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); +// mmwrite(MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); + mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); mmwrite(0, MANTIS_DMA_CTL); mantis->last_block = mantis->finished_block = 0; @@ -210,6 +211,8 @@ void mantis_dma_stop(struct mantis_pci *mantis) mask = mmread(MANTIS_INT_MASK); dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); + mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_RDWRN))), MANTIS_GPIF_ADDR); + mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | MANTIS_DCAP_EN | MANTIS_RISC_EN)), MANTIS_DMA_CTL); -- cgit v1.2.3-70-g09d2 From e2f67e4fb931b975058b3bd48eaac43780c92c88 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:42:10 -0300 Subject: V4L/DVB (13712): [Mantis] Add locking for concurrent access Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 ++ drivers/media/dvb/mantis/mantis_i2c.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 197393e700f..e354e7678a5 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "dvbdev.h" #include "dvb_demux.h" @@ -109,6 +110,7 @@ struct mantis_pci { struct i2c_adapter adapter; int i2c_rc; wait_queue_head_t i2c_wq; + struct mutex i2c_lock; /* DVB stuff */ struct dvb_adapter dvb_adapter; diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 53c5f88227b..39fabe572c2 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -125,6 +125,7 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in struct mantis_pci *mantis; mantis = i2c_get_adapdata(adapter); + mutex_lock(&mantis->i2c_lock); for (i = 0; i < num; i++) { if (msgs[i].flags & I2C_M_RD) ret = mantis_i2c_read(mantis, &msgs[i]); @@ -134,6 +135,7 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in if (ret < 0) return ret; } + mutex_unlock(&mantis->i2c_lock); return num; } @@ -160,6 +162,7 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) { u32 intstat, intmask; + mutex_init(&mantis->i2c_lock); memcpy(&mantis->adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); i2c_set_adapdata(&mantis->adapter, mantis); mantis->i2c_rc = i2c_add_adapter(&mantis->adapter); -- cgit v1.2.3-70-g09d2 From 1fa1f107852484157c5453cc6c4a60c792f06c35 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Thu, 3 Dec 2009 05:44:00 -0300 Subject: V4L/DVB (13713): [MB86A16] Fix: Initialize SNR/STATUS Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 361e4762346..4f8ef2e2ecd 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -595,6 +595,7 @@ static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status) { struct mb86a16_state *state = fe->demodulator_priv; + *status = 0; if (state->signal & 0x02) *status |= FE_HAS_VITERBI; if (state->signal & 0x01) @@ -1693,6 +1694,7 @@ static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr) int low_tide = 2, high_tide = 30, q_level; u8 cn; + *snr = 0; if (mb86a16_read(state, 0x26, &cn) != 2) { dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); return -EREMOTEIO; -- cgit v1.2.3-70-g09d2 From 33c79630dd9fb7658dbb885a22e3a8127b16a38a Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:44:38 -0300 Subject: V4L/DVB (13714): [MB86A16] FIX/Code simplification: use hwconfig->ts_size instead of ts_size thanks to Marko Ristola for pointing it out Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 1 - drivers/media/dvb/mantis/mantis_dma.c | 4 ++-- drivers/media/dvb/mantis/mantis_dvb.c | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index e354e7678a5..d4865e4f346 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -92,7 +92,6 @@ struct mantis_pci { u8 revision; unsigned int num; - u16 ts_size; /* RISC Core */ u32 finished_block; diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index e207870fb45..ea23a89c03f 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -190,7 +190,6 @@ void mantis_dma_start(struct mantis_pci *mantis) mantis_risc_program(mantis); mmwrite(cpu_to_le32(mantis->risc_dma), MANTIS_RISC_START); -// mmwrite(MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); mmwrite(0, MANTIS_DMA_CTL); @@ -227,12 +226,13 @@ void mantis_dma_stop(struct mantis_pci *mantis) void mantis_dma_xfer(unsigned long data) { struct mantis_pci *mantis = (struct mantis_pci *) data; + struct mantis_hwconfig *config = mantis->hwconfig; while (mantis->last_block != mantis->finished_block) { dprintk(verbose, MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", mantis->last_block, mantis->finished_block); - (mantis->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) + (config->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT; } diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 319bb8bef4e..7fe8541b1c5 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -142,7 +142,6 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) mantis->demux.start_feed = mantis_dvb_start_feed; mantis->demux.stop_feed = mantis_dvb_stop_feed; mantis->demux.write_to_decoder = NULL; - mantis->ts_size = 1; //188 dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmx_init"); if ((result = dvb_dmx_init(&mantis->demux)) < 0) { dprintk(verbose, MANTIS_ERROR, 1, -- cgit v1.2.3-70-g09d2 From 8154bad4c488c1a23fb504a6e751d71a39733b76 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:46:06 -0300 Subject: V4L/DVB (13715): [Mantis] Kernel I2C changes: use PCI parent device Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 +- drivers/media/dvb/mantis/mantis_i2c.c | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index d4865e4f346..34d2389f312 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -83,7 +83,7 @@ struct mantis_pci { u8 latency; - struct pci_dev *pdev; + struct pci_dev *pdev; unsigned long mantis_addr; volatile void __iomem *mantis_mmio; diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 39fabe572c2..005df1e90a1 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -161,11 +161,15 @@ static struct i2c_adapter mantis_i2c_adapter = { int __devinit mantis_i2c_init(struct mantis_pci *mantis) { u32 intstat, intmask; + struct i2c_adapter *i2c_adapter = &mantis->adapter; + struct pci_dev *pdev = mantis->pdev; mutex_init(&mantis->i2c_lock); - memcpy(&mantis->adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); - i2c_set_adapdata(&mantis->adapter, mantis); - mantis->i2c_rc = i2c_add_adapter(&mantis->adapter); + memcpy(i2c_adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); + i2c_set_adapdata(i2c_adapter, mantis); + + i2c_adapter->dev.parent = &pdev->dev; + mantis->i2c_rc = i2c_add_adapter(i2c_adapter); if (mantis->i2c_rc < 0) return mantis->i2c_rc; -- cgit v1.2.3-70-g09d2 From 417036844823313901d7f7d7b963f215cc3b0641 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 3 Dec 2009 05:47:11 -0300 Subject: V4L/DVB (13716): [Mantis] Bug: incorrect byte swap You know, the worst endianness errors are not the cases where people forget to byte-swap, but the cases where they either byte-swap with the wrong size, or byte-swap when they shouldn't have done so at all. Those ones defeat the casual reader of the code. Signed-off-by: David Woodhouse Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index ea23a89c03f..f685992f7d0 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -189,7 +189,7 @@ void mantis_dma_start(struct mantis_pci *mantis) dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Start DMA engine"); mantis_risc_program(mantis); - mmwrite(cpu_to_le32(mantis->risc_dma), MANTIS_RISC_START); + mmwrite(mantis->risc_dma, MANTIS_RISC_START); mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); mmwrite(0, MANTIS_DMA_CTL); -- cgit v1.2.3-70-g09d2 From 77557abef0de3f1f1e8f563db6df8710a9e930fe Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:48:13 -0300 Subject: V4L/DVB (13717): [MB86A16] Statistics Updates * Demodulator status check made reliable * Code simplification for Viterbi Sync check, makes acquisition more reliable * Implement a BER monitor * Implement a Signal strength monitor * Implement a "simple" UCB monitor, no real UCB monitor Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 142 ++++++++++++++++++++++++++++------ 1 file changed, 117 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 4f8ef2e2ecd..eddb35baaf0 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -36,7 +36,6 @@ struct mb86a16_state { struct i2c_adapter *i2c_adap; const struct mb86a16_config *config; struct dvb_frontend frontend; - u8 signal; // tuning parameters int frequency; @@ -593,17 +592,39 @@ err: static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status) { + u8 stat, stat2; struct mb86a16_state *state = fe->demodulator_priv; *status = 0; - if (state->signal & 0x02) - *status |= FE_HAS_VITERBI; - if (state->signal & 0x01) + + if (mb86a16_read(state, MB86A16_SIG1, &stat) != 2) + goto err; + if (mb86a16_read(state, MB86A16_SIG2, &stat2) != 2) + goto err; + if ((stat > 25) && (stat2 > 25)) + *status |= FE_HAS_SIGNAL; + if ((stat > 45) && (stat2 > 45)) + *status |= FE_HAS_CARRIER; + + if (mb86a16_read(state, MB86A16_STATUS, &stat) != 2) + goto err; + + if (stat & 0x01) *status |= FE_HAS_SYNC; - if (state->signal & 0x03) + if (stat & 0x01) + *status |= FE_HAS_VITERBI; + + if (mb86a16_read(state, MB86A16_FRAMESYNC, &stat) != 2) + goto err; + + if ((stat & 0x0f) && (*status & FE_HAS_VITERBI)) *status |= FE_HAS_LOCK; return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; } static int sync_chk(struct mb86a16_state *state, @@ -1439,10 +1460,6 @@ static int mb86a16_set_fe(struct mb86a16_state *state) msleep_interruptible(wait_t); sync = sync_chk(state, &VIRM); dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync); - if (mb86a16_read(state, 0x0d, &state->signal) != 2) { - dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); - return -EREMOTEIO; - } if (VIRM) { if (VIRM == 4) { // 5/6 if (SIG1 > 110) @@ -1459,22 +1476,14 @@ static int mb86a16_set_fe(struct mb86a16_state *state) iq_vt_set(state, 1); FEC_srst(state); } - if (SIG1 > 110) - wait_t = ( 786432 + state->srate / 2) / state->srate; - else - wait_t = (1572864 + state->srate / 2) / state->srate; - - msleep_interruptible(wait_t); - SEQ_set(state, 1); - } else { // 1/2, 2/3, 3/4, 7/8 - if (SIG1 > 110) - wait_t = ( 786432 + state->srate / 2) / state->srate; - else - wait_t = (1572864 + state->srate / 2) / state->srate; - - msleep_interruptible(wait_t); - SEQ_set(state, 1); } + // 1/2, 2/3, 3/4, 7/8 + if (SIG1 > 110) + wait_t = ( 786432 + state->srate / 2) / state->srate; + else + wait_t = (1572864 + state->srate / 2) / state->srate; + msleep_interruptible(wait_t); + SEQ_set(state, 1); } else { dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC"); SEQ_set(state, 1); @@ -1648,12 +1657,85 @@ static int mb86a16_sleep(struct dvb_frontend *fe) static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber) { + u8 ber_mon, ber_tab, ber_lsb, ber_mid, ber_msb, ber_tim, ber_rst; + u32 timer; + + struct mb86a16_state *state = fe->demodulator_priv; + + *ber = 0; + if (mb86a16_read(state, MB86A16_BERMON, &ber_mon) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERTAB, &ber_tab) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERLSB, &ber_lsb) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERMID, &ber_mid) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERMSB, &ber_msb) != 2) + goto err; + /* BER monitor invalid when BER_EN = 0 */ + if (ber_mon & 0x04) { + /* coarse, fast calculation */ + *ber = ber_tab & 0x1f; + dprintk(verbose, MB86A16_DEBUG, 1, "BER coarse=[0x%02x]", *ber); + if (ber_mon & 0x01) { + /* + * BER_SEL = 1, The monitored BER is the estimated + * value with a Reed-Solomon decoder error amount at + * the deinterleaver output. + * monitored BER is expressed as a 20 bit output in total + */ + ber_rst = ber_mon >> 3; + *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb; + if (ber_rst == 0) + timer = 12500000; + if (ber_rst == 1) + timer = 25000000; + if (ber_rst == 2) + timer = 50000000; + if (ber_rst == 3) + timer = 100000000; + + *ber /= timer; + dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber); + } else { + /* + * BER_SEL = 0, The monitored BER is the estimated + * value with a Viterbi decoder error amount at the + * QPSK demodulator output. + * monitored BER is expressed as a 24 bit output in total + */ + ber_tim = ber_mon >> 1; + *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb; + if (ber_tim == 0) + timer = 16; + if (ber_tim == 1) + timer = 24; + + *ber /= 2 ^ timer; + dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber); + } + } return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; } static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { + u8 agcm = 0; + struct mb86a16_state *state = fe->demodulator_priv; + *strength = 0; + if (mb86a16_read(state, MB86A16_AGCM, &agcm) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + *strength = ((0xff - agcm) * 100) / 256; + dprintk(verbose, MB86A16_DEBUG, 1, "Signal strength=[%d %%]", (u8) *strength); + *strength = (0xffff - 0xff) + agcm; return 0; } @@ -1708,12 +1790,22 @@ static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr) } q_level = (*snr * 100) / (high_tide - low_tide); dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level); + *snr = (0xffff - 0xff) + *snr; return 0; } static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { + u8 dist; + struct mb86a16_state *state = fe->demodulator_priv; + + if (mb86a16_read(state, MB86A16_DISTMON, &dist) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + *ucblocks = dist; + return 0; } @@ -1723,7 +1815,7 @@ static struct dvb_frontend_ops mb86a16_ops = { .type = FE_QPSK, .frequency_min = 950000, .frequency_max = 2150000, - .frequency_stepsize = 125, + .frequency_stepsize = 3000, .frequency_tolerance = 0, .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, -- cgit v1.2.3-70-g09d2 From f8e26cdec5ac25ae8d73e278e21033292de5430b Mon Sep 17 00:00:00 2001 From: Marko Ristola Date: Fri, 4 Dec 2009 04:35:35 -0300 Subject: V4L/DVB (13718): [Mantis] Use gpio_set_bits to turn OFF the bits as well Signed-off-by: Marko Ristola Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index d159ad6fc32..16d693eeb29 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -172,25 +172,23 @@ int mantis_core_exit(struct mantis_pci *mantis) return 0; } +// Turn the given bit on or off. void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) { - u32 reg; + u32 currVal, newVal; + + currVal = mmread(MANTIS_GPIF_ADDR); if (value) - reg = 0x0000; + newVal = currVal | (1 << bitpos); else - reg = 0xffff; - - reg = (value << bitpos); + newVal = currVal & (~(1 << bitpos)); - mmwrite(mmread(MANTIS_GPIF_ADDR) | reg, MANTIS_GPIF_ADDR); + mmwrite(newVal, MANTIS_GPIF_ADDR); mmwrite(0x00, MANTIS_GPIF_DOUT); udelay(100); - mmwrite(mmread(MANTIS_GPIF_ADDR) | reg, MANTIS_GPIF_ADDR); - mmwrite(0x00, MANTIS_GPIF_DOUT); } - //direction = 0 , no CI passthrough ; 1 , CI passthrough void mantis_set_direction(struct mantis_pci *mantis, int direction) { -- cgit v1.2.3-70-g09d2 From 2687d832fe0141015e2391f3755d9499e6efb83e Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:39:14 -0300 Subject: V4L/DVB (13719): [Mantis/VP-2033] Initial test switch to the tda10021, from the cu1216 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 2 +- drivers/media/dvb/mantis/mantis_vp2033.c | 80 +++++++++++++++++++++++--------- drivers/media/dvb/mantis/mantis_vp2033.h | 8 ++-- 3 files changed, 63 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 7fe8541b1c5..f2556950d18 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -239,7 +239,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) break; case MANTIS_VP_2033_DVB_C: // VP-2033 dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - mantis->fe = cu1216_attach(&philips_cu1216_config, &mantis->adapter); + mantis->fe = tda10021_attach(&philips_cu1216_config, &mantis->adapter, read_pwm(mantis)); if (mantis->fe) { mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; dprintk(verbose, MANTIS_ERROR, 1, diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 15772fe5828..4664d295921 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -27,44 +27,80 @@ struct mantis_hwconfig vp2033_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_188, + .ts_size = MANTIS_TS_204, }; -struct cu1216_config philips_cu1216_config = { - .demod_address = 0x18 >> 1, - .pll_set = philips_cu1216_tuner_set, -// .fe_reset = mantis_fe_reset, +struct tda1002x_config philips_cu1216_config = { + .demod_address = 0x18 >> 1, + .invert = 1, }; -int philips_cu1216_tuner_set(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params) +u8 read_pwm(struct mantis_pci *mantis) { - struct mantis_pci *mantis = fe->dvb->priv; + u8 b = 0xff; + u8 pwm; + struct i2c_msg msg[] = { + {.addr = 0x50,.flags = 0,.buf = &b,.len = 1}, + {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} + }; - u8 buf[4]; + if ((i2c_transfer(&mantis->adapter, msg, 2) != 2) + || (pwm == 0xff)) + pwm = 0x48; - struct i2c_msg msg = { - .addr = 0xc0 >> 1, - .flags = 0, - .buf = buf, - .len = sizeof (buf) - }; + return pwm; +} + +int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct mantis_pci *mantis = fe->dvb->priv; + + u8 buf[6]; + struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; + int i; +#define CU1216_IF 36125000 #define TUNER_MUL 62500 - u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL; + u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL; buf[0] = (div >> 8) & 0x7f; buf[1] = div & 0xff; - buf[2] = 0x86; - buf[3] = (params->frequency < 150000000 ? 0xA1 : - params->frequency < 445000000 ? 0x92 : 0x34); + buf[2] = 0xce; + buf[3] = (params->frequency < 150000000 ? 0x01 : + params->frequency < 445000000 ? 0x02 : 0x04); + buf[4] = 0xde; + buf[5] = 0x20; - if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { - printk("%s tuner not ack!\n", __FUNCTION__); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(&mantis->adapter, &msg, 1) != 1) return -EIO; + + /* wait for the pll lock */ + msg.flags = I2C_M_RD; + msg.len = 1; + for (i = 0; i < 20; i++) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(&mantis->adapter, &msg, 1) == 1 && (buf[0] & 0x40)) + break; + + msleep(10); } - msleep(100); + + /* switch the charge pump to the lower current */ + msg.flags = 0; + msg.len = 2; + msg.buf = &buf[2]; + buf[2] &= ~0x40; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(&mantis->adapter, &msg, 1) != 1) + return -EIO; return 0; } diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index 513c491942c..fcf8b85be94 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -23,15 +23,15 @@ #include "dvb_frontend.h" #include "mantis_common.h" -#include "cu1216.h" +#include "tda1002x.h" #define MANTIS_VP_2033_DVB_C 0x0008 -extern struct cu1216_config philips_cu1216_config; +extern struct tda1002x_config philips_cu1216_config; extern struct mantis_hwconfig vp2033_mantis_config; -extern int philips_cu1216_tuner_set(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params); +extern int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params); +extern u8 read_pwm(struct mantis_pci *mantis); #endif // __MANTIS_VP2033_H -- cgit v1.2.3-70-g09d2 From 51d20db8bb9c5a14ac2320664289f13bd52625c6 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:39:48 -0300 Subject: V4L/DVB (13720): [Mantis/Terratec Cinergy C] Add support for the Terratec Cinergy C PCI Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 1 + drivers/media/dvb/mantis/mantis_dvb.c | 13 +++++++++++++ drivers/media/dvb/mantis/mantis_vp2033.h | 1 + 3 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 16d693eeb29..3b5fea7d8d5 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -111,6 +111,7 @@ static void mantis_load_config(struct mantis_pci *mantis) mantis->hwconfig = &vp1034_mantis_config; break; case MANTIS_VP_2033_DVB_C: // VP-2033 + case TERRATEC_CINERGY_C_PCI: // Terratec Cinergy C PCI mantis->hwconfig = &vp2033_mantis_config; break; case MANTIS_VP_3030_DVB_T: // VP-3030 diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index f2556950d18..e2aec0c7f02 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -251,6 +251,19 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; + case TERRATEC_CINERGY_C_PCI: + dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + mantis->fe = tda10023_attach(&philips_cu1216_config, &mantis->adapter, read_pwm(mantis)); + if (mantis->fe) { + mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; + dprintk(verbose, MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend 0x%02x", + philips_cu1216_config.demod_address); + + dprintk(verbose, MANTIS_ERROR, 1, + "Mantis DVB-C Philips CU1216 frontend attach success"); + } + break; default: dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", mantis->sub_device_id); diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index fcf8b85be94..0a753f7f742 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -26,6 +26,7 @@ #include "tda1002x.h" #define MANTIS_VP_2033_DVB_C 0x0008 +#define TERRATEC_CINERGY_C_PCI 0x1178 extern struct tda1002x_config philips_cu1216_config; extern struct mantis_hwconfig vp2033_mantis_config; -- cgit v1.2.3-70-g09d2 From 99d96e4e9202aa046e3e2be1813ff59c84e67608 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:40:16 -0300 Subject: V4L/DVB (13721): [Mantis] Bug! Before bailing out, Unlock Thanks to hotwings for pointing out the bug Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_i2c.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 005df1e90a1..45d9e6bd962 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -133,11 +133,15 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in ret = mantis_i2c_write(mantis, &msgs[i]); if (ret < 0) - return ret; + goto bail_out; } mutex_unlock(&mantis->i2c_lock); return num; + +bail_out: + mutex_unlock(&mantis->i2c_lock); + return ret; } static u32 mantis_i2c_func(struct i2c_adapter *adapter) -- cgit v1.2.3-70-g09d2 From 5e68b0aedaa34447d86ae5cc6d071251c62bef37 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:40:50 -0300 Subject: V4L/DVB (13722): [Mantis] Revert 13560 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 1 - drivers/media/dvb/mantis/mantis_dvb.c | 13 ------------- drivers/media/dvb/mantis/mantis_vp2033.h | 1 - 3 files changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 3b5fea7d8d5..16d693eeb29 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -111,7 +111,6 @@ static void mantis_load_config(struct mantis_pci *mantis) mantis->hwconfig = &vp1034_mantis_config; break; case MANTIS_VP_2033_DVB_C: // VP-2033 - case TERRATEC_CINERGY_C_PCI: // Terratec Cinergy C PCI mantis->hwconfig = &vp2033_mantis_config; break; case MANTIS_VP_3030_DVB_T: // VP-3030 diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index e2aec0c7f02..f2556950d18 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -251,19 +251,6 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; - case TERRATEC_CINERGY_C_PCI: - dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - mantis->fe = tda10023_attach(&philips_cu1216_config, &mantis->adapter, read_pwm(mantis)); - if (mantis->fe) { - mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; - dprintk(verbose, MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend 0x%02x", - philips_cu1216_config.demod_address); - - dprintk(verbose, MANTIS_ERROR, 1, - "Mantis DVB-C Philips CU1216 frontend attach success"); - } - break; default: dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", mantis->sub_device_id); diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index 0a753f7f742..fcf8b85be94 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -26,7 +26,6 @@ #include "tda1002x.h" #define MANTIS_VP_2033_DVB_C 0x0008 -#define TERRATEC_CINERGY_C_PCI 0x1178 extern struct tda1002x_config philips_cu1216_config; extern struct mantis_hwconfig vp2033_mantis_config; -- cgit v1.2.3-70-g09d2 From b2eb1312faa26703e71b7b3945c8773213e9ee49 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:42:22 -0300 Subject: V4L/DVB (13723): [Mantis/VP-2040, Terratec Cinergy C] Add support for the Cinergy C, VP-2040 clone Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 13 +++++++++--- drivers/media/dvb/mantis/mantis_core.c | 4 ++++ drivers/media/dvb/mantis/mantis_dvb.c | 16 +++++++++++++- drivers/media/dvb/mantis/mantis_vp2040.c | 36 ++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_vp2040.h | 33 +++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 drivers/media/dvb/mantis/mantis_vp2040.c create mode 100644 drivers/media/dvb/mantis/mantis_vp2040.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index a980ff2382b..2be21bfdd24 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -1,6 +1,13 @@ -mantis-objs = mantis_core.o mantis_dma.o mantis_pci.o mantis_i2c.o \ - mantis_dvb.o mantis_vp1033.o mantis_vp1034.o mantis_vp2033.o \ - mantis_vp3030.o +mantis-objs = mantis_core.o \ + mantis_dma.o \ + mantis_pci.o \ + mantis_i2c.o \ + mantis_dvb.o \ + mantis_vp1033.o \ + mantis_vp1034.o \ + mantis_vp2033.o \ + mantis_vp2040.o \ + mantis_vp3030.o obj-$(CONFIG_DVB_MANTIS) += mantis.o diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 16d693eeb29..96b939247b4 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -23,6 +23,7 @@ #include "mantis_vp1033.h" #include "mantis_vp1034.h" #include "mantis_vp2033.h" +#include "mantis_vp2040.h" #include "mantis_vp3030.h" static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) @@ -113,6 +114,9 @@ static void mantis_load_config(struct mantis_pci *mantis) case MANTIS_VP_2033_DVB_C: // VP-2033 mantis->hwconfig = &vp2033_mantis_config; break; + case TERRATEC_CINERGY_C_PCI: // VP-2040 clone + mantis->hwconfig = &vp2040_mantis_config; + break; case MANTIS_VP_3030_DVB_T: // VP-3030 mantis->hwconfig = &vp3030_mantis_config; break; diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index f2556950d18..15012ea5796 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -28,6 +28,7 @@ #include "mantis_vp1033.h" #include "mantis_vp1034.h" #include "mantis_vp2033.h" +#include "mantis_vp2040.h" #include "mantis_vp3030.h" /* Tuner power supply control */ @@ -243,7 +244,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) if (mantis->fe) { mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; dprintk(verbose, MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend @ 0x%02x", + "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", philips_cu1216_config.demod_address); dprintk(verbose, MANTIS_ERROR, 1, @@ -251,6 +252,19 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; + case TERRATEC_CINERGY_C_PCI: + dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + mantis->fe = tda10023_attach(&tda10023_cu1216_config, &mantis->adapter, read_pwm(mantis)); + if (mantis->fe) { + mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; + dprintk(verbose, MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + philips_cu1216_config.demod_address); + + dprintk(verbose, MANTIS_ERROR, 1, + "Mantis DVB-C Philips CU1216 frontend attach success"); + } + break; default: dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", mantis->sub_device_id); diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c new file mode 100644 index 00000000000..07da73827fd --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -0,0 +1,36 @@ +/* + Mantis VP-2040 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp2040.h" + +#define MANTIS_MODEL_NAME "VP-2040" +#define MANTIS_DEV_TYPE "DVB-C" + +struct mantis_hwconfig vp2040_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, +}; + +struct tda1002x_config tda10023_cu1216_config = { + .demod_address = 0x18 >> 1, + .invert = 1, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h new file mode 100644 index 00000000000..825ccbb87ad --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2040.h @@ -0,0 +1,33 @@ +/* + Mantis VP-2040 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP2040_H +#define __MANTIS_VP2040_H + +#include "dvb_frontend.h" +#include "mantis_common.h" +#include "tda1002x.h" + +#define TERRATEC_CINERGY_C_PCI 0x1178 + +extern struct tda1002x_config tda10023_cu1216_config; +extern struct mantis_hwconfig vp2040_mantis_config; + +#endif //__MANTIS_VP2040_H -- cgit v1.2.3-70-g09d2 From 873c8c25ebca50bd60e21784c4d442c4fecb8658 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:43:04 -0300 Subject: V4L/DVB (13724): [Mantis/VP-1041] Initial support for Mantis VP-1041 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 1 + drivers/media/dvb/mantis/mantis_core.c | 4 + drivers/media/dvb/mantis/mantis_dvb.c | 18 ++ drivers/media/dvb/mantis/mantis_vp1041.c | 295 +++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_vp1041.h | 36 ++++ 5 files changed, 354 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_vp1041.c create mode 100644 drivers/media/dvb/mantis/mantis_vp1041.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index 2be21bfdd24..bdf3e3629ab 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -5,6 +5,7 @@ mantis-objs = mantis_core.o \ mantis_dvb.o \ mantis_vp1033.o \ mantis_vp1034.o \ + mantis_vp1041.o \ mantis_vp2033.o \ mantis_vp2040.o \ mantis_vp3030.o diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 96b939247b4..47cfb759f0b 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -22,6 +22,7 @@ #include "mantis_core.h" #include "mantis_vp1033.h" #include "mantis_vp1034.h" +#include "mantis_vp1041.h" #include "mantis_vp2033.h" #include "mantis_vp2040.h" #include "mantis_vp3030.h" @@ -111,6 +112,9 @@ static void mantis_load_config(struct mantis_pci *mantis) case MANTIS_VP_1034_DVB_S: // VP-1034 mantis->hwconfig = &vp1034_mantis_config; break; + case MANTIS_VP_1041_DVB_S2: // VP-1041 + mantis->hwconfig = &vp1041_mantis_config; + break; case MANTIS_VP_2033_DVB_C: // VP-2033 mantis->hwconfig = &vp2033_mantis_config; break; diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 15012ea5796..a4750bb22b0 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -27,6 +27,7 @@ #include "dvb_frontend.h" #include "mantis_vp1033.h" #include "mantis_vp1034.h" +#include "mantis_vp1041.h" #include "mantis_vp2033.h" #include "mantis_vp2040.h" #include "mantis_vp3030.h" @@ -238,6 +239,23 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; + case MANTIS_VP_1041_DVB_S2: + mantis->fe = stb0899_attach(&vp1041_config, &mantis->adapter); + if (mantis->fe) { + dprintk(verbose, MANTIS_ERROR, 1, + "found STB0899 DVB-S/DVB-S2 frontend @0x%02x", + vp1041_config.demod_address); + + if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, &mantis->adapter)) { + if (!lnbp21_attach(mantis->fe, &mantis->adapter, 0, 0)) { + printk("%s: No LNBP21 found!\n", __FUNCTION__); + mantis->fe = NULL; + } + } else { + mantis->fe = NULL; + } + } + break; case MANTIS_VP_2033_DVB_C: // VP-2033 dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); mantis->fe = tda10021_attach(&philips_cu1216_config, &mantis->adapter, read_pwm(mantis)); diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c new file mode 100644 index 00000000000..a3279f0e4b9 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -0,0 +1,295 @@ +/* + Mantis VP-1041 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp1041.h" +#include "stb0899_reg.h" +#include "stb0899_cfg.h" +#include "stb6100_cfg.h" + +#define MANTIS_MODEL_NAME "VP-1041" +#define MANTIS_DEV_TYPE "DSS/DVB-S/DVB-S2" + +struct mantis_hwconfig vp1041_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, +}; + +static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { + +// 0x0000000b , /* SYSREG */ + { STB0899_DEV_ID , 0x30 }, + { STB0899_DISCNTRL1 , 0x32 }, + { STB0899_DISCNTRL2 , 0x80 }, + { STB0899_DISRX_ST0 , 0x04 }, + { STB0899_DISRX_ST1 , 0x00 }, + { STB0899_DISPARITY , 0x00 }, + { STB0899_DISFIFO , 0x00 }, + { STB0899_DISSTATUS , 0x20 }, + { STB0899_DISF22 , 0x99 }, + { STB0899_DISF22RX , 0xa8 }, + //SYSREG ? + { STB0899_ACRPRESC , 0x11 }, + { STB0899_ACRDIV1 , 0x0a }, + { STB0899_ACRDIV2 , 0x05 }, + { STB0899_DACR1 , 0x00 }, + { STB0899_DACR2 , 0x00 }, + { STB0899_OUTCFG , 0x00 }, + { STB0899_MODECFG , 0x00 }, + { STB0899_IRQSTATUS_3 , 0xfe }, + { STB0899_IRQSTATUS_2 , 0x03 }, + { STB0899_IRQSTATUS_1 , 0x7c }, + { STB0899_IRQSTATUS_0 , 0xf4 }, + { STB0899_IRQMSK_3 , 0xf3 }, + { STB0899_IRQMSK_2 , 0xfc }, + { STB0899_IRQMSK_1 , 0xff }, + { STB0899_IRQMSK_0 , 0xff }, + { STB0899_IRQCFG , 0x00 }, + { STB0899_I2CCFG , 0x88 }, + { STB0899_I2CRPT , 0x5c }, + { STB0899_IOPVALUE5 , 0x00 }, + { STB0899_IOPVALUE4 , 0x33 }, + { STB0899_IOPVALUE3 , 0x6d }, + { STB0899_IOPVALUE2 , 0x90 }, + { STB0899_IOPVALUE1 , 0x60 }, + { STB0899_IOPVALUE0 , 0x00 }, + { STB0899_GPIO00CFG , 0x82 }, + { STB0899_GPIO01CFG , 0x82 }, + { STB0899_GPIO02CFG , 0x82 }, + { STB0899_GPIO03CFG , 0x82 }, + { STB0899_GPIO04CFG , 0x82 }, + { STB0899_GPIO05CFG , 0x82 }, + { STB0899_GPIO06CFG , 0x82 }, + { STB0899_GPIO07CFG , 0x82 }, + { STB0899_GPIO08CFG , 0x82 }, + { STB0899_GPIO09CFG , 0x82 }, + { STB0899_GPIO10CFG , 0x82 }, + { STB0899_GPIO11CFG , 0x82 }, + { STB0899_GPIO12CFG , 0x82 }, + { STB0899_GPIO13CFG , 0x82 }, + { STB0899_GPIO14CFG , 0x82 }, + { STB0899_GPIO15CFG , 0x82 }, + { STB0899_GPIO16CFG , 0x82 }, + { STB0899_GPIO17CFG , 0x82 }, + { STB0899_GPIO18CFG , 0x82 }, + { STB0899_GPIO19CFG , 0x82 }, + { STB0899_GPIO20CFG , 0x82 }, + { STB0899_SDATCFG , 0xb8 }, + { STB0899_SCLTCFG , 0xba }, + { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */ + { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */ + { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */ + { STB0899_DIRCLKCFG , 0x82 }, + { STB0899_CLKOUT27CFG , 0x7e }, + { STB0899_STDBYCFG , 0x82 }, + { STB0899_CS0CFG , 0x82 }, + { STB0899_CS1CFG , 0x82 }, + { STB0899_DISEQCOCFG , 0x20 }, + { STB0899_GPIO32CFG , 0x82 }, + { STB0899_GPIO33CFG , 0x82 }, + { STB0899_GPIO34CFG , 0x82 }, + { STB0899_GPIO35CFG , 0x82 }, + { STB0899_GPIO36CFG , 0x82 }, + { STB0899_GPIO37CFG , 0x82 }, + { STB0899_GPIO38CFG , 0x82 }, + { STB0899_GPIO39CFG , 0x82 }, + { STB0899_NCOARSE , 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */ + { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */ + { STB0899_FILTCTRL , 0x00 }, + { STB0899_SYSCTRL , 0x01 }, + { STB0899_STOPCLK1 , 0x20 }, + { STB0899_STOPCLK2 , 0x00 }, + { STB0899_INTBUFSTATUS , 0x00 }, + { STB0899_INTBUFCTRL , 0x0a }, + { 0xffff , 0xff }, +}; + +static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { + { STB0899_DEMOD , 0x00 }, + { STB0899_RCOMPC , 0xc9 }, + { STB0899_AGC1CN , 0x41 }, + { STB0899_AGC1REF , 0x10 }, + { STB0899_RTC , 0x7a }, + { STB0899_TMGCFG , 0x4e }, + { STB0899_AGC2REF , 0x34 }, + { STB0899_TLSR , 0x84 }, + { STB0899_CFD , 0xc7 }, + { STB0899_ACLC , 0x87 }, + { STB0899_BCLC , 0x94 }, + { STB0899_EQON , 0x41 }, + { STB0899_LDT , 0xdd }, + { STB0899_LDT2 , 0xc9 }, + { STB0899_EQUALREF , 0xb4 }, + { STB0899_TMGRAMP , 0x10 }, + { STB0899_TMGTHD , 0x30 }, + { STB0899_IDCCOMP , 0xfb }, + { STB0899_QDCCOMP , 0x03 }, + { STB0899_POWERI , 0x3b }, + { STB0899_POWERQ , 0x3d }, + { STB0899_RCOMP , 0x81 }, + { STB0899_AGCIQIN , 0x80 }, + { STB0899_AGC2I1 , 0x04 }, + { STB0899_AGC2I2 , 0xf5 }, + { STB0899_TLIR , 0x25 }, + { STB0899_RTF , 0x80 }, + { STB0899_DSTATUS , 0x00 }, + { STB0899_LDI , 0xca }, + { STB0899_CFRM , 0xf1 }, + { STB0899_CFRL , 0xf3 }, + { STB0899_NIRM , 0x2a }, + { STB0899_NIRL , 0x05 }, + { STB0899_ISYMB , 0x17 }, + { STB0899_QSYMB , 0xfa }, + { STB0899_SFRH , 0x2f }, + { STB0899_SFRM , 0x68 }, + { STB0899_SFRL , 0x40 }, + { STB0899_SFRUPH , 0x2f }, + { STB0899_SFRUPM , 0x68 }, + { STB0899_SFRUPL , 0x40 }, + { STB0899_EQUAI1 , 0xfd }, + { STB0899_EQUAQ1 , 0x04 }, + { STB0899_EQUAI2 , 0x0f }, + { STB0899_EQUAQ2 , 0xff }, + { STB0899_EQUAI3 , 0xdf }, + { STB0899_EQUAQ3 , 0xfa }, + { STB0899_EQUAI4 , 0x37 }, + { STB0899_EQUAQ4 , 0x0d }, + { STB0899_EQUAI5 , 0xbd }, + { STB0899_EQUAQ5 , 0xf7 }, + { STB0899_DSTATUS2 , 0x00 }, + { STB0899_VSTATUS , 0x00 }, + { STB0899_VERROR , 0xff }, + { STB0899_IQSWAP , 0x2a }, + { STB0899_ECNT1M , 0x00 }, + { STB0899_ECNT1L , 0x00 }, + { STB0899_ECNT2M , 0x00 }, + { STB0899_ECNT2L , 0x00 }, + { STB0899_ECNT3M , 0x00 }, + { STB0899_ECNT3L , 0x00 }, + { STB0899_FECAUTO1 , 0x06 }, + { STB0899_FECM , 0x01 }, + { STB0899_VTH12 , 0xf0 }, + { STB0899_VTH23 , 0xa0 }, + { STB0899_VTH34 , 0x78 }, + { STB0899_VTH56 , 0x4e }, + { STB0899_VTH67 , 0x48 }, + { STB0899_VTH78 , 0x38 }, + { STB0899_PRVIT , 0xff }, + { STB0899_VITSYNC , 0x19 }, + { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ + { STB0899_TSULC , 0x42 }, + { STB0899_RSLLC , 0x40 }, + { STB0899_TSLPL , 0x12 }, + { STB0899_TSCFGH , 0x0c }, + { STB0899_TSCFGM , 0x00 }, + { STB0899_TSCFGL , 0x0c }, + { STB0899_TSOUT , 0x0d }, /* 0x0d for CAM */ + { STB0899_RSSYNCDEL , 0x00 }, + { STB0899_TSINHDELH , 0x02 }, + { STB0899_TSINHDELM , 0x00 }, + { STB0899_TSINHDELL , 0x00 }, + { STB0899_TSLLSTKM , 0x00 }, + { STB0899_TSLLSTKL , 0x00 }, + { STB0899_TSULSTKM , 0x00 }, + { STB0899_TSULSTKL , 0xab }, + { STB0899_PCKLENUL , 0x00 }, + { STB0899_PCKLENLL , 0xcc }, + { STB0899_RSPCKLEN , 0xcc }, + { STB0899_TSSTATUS , 0x80 }, + { STB0899_ERRCTRL1 , 0xb6 }, + { STB0899_ERRCTRL2 , 0x96 }, + { STB0899_ERRCTRL3 , 0x89 }, + { STB0899_DMONMSK1 , 0x27 }, + { STB0899_DMONMSK0 , 0x03 }, + { STB0899_DEMAPVIT , 0x5c }, + { STB0899_PLPARM , 0x1f }, + { STB0899_PDELCTRL , 0x48 }, + { STB0899_PDELCTRL2 , 0x00 }, + { STB0899_BBHCTRL1 , 0x00 }, + { STB0899_BBHCTRL2 , 0x00 }, + { STB0899_HYSTTHRESH , 0x77 }, + { STB0899_MATCSTM , 0x00 }, + { STB0899_MATCSTL , 0x00 }, + { STB0899_UPLCSTM , 0x00 }, + { STB0899_UPLCSTL , 0x00 }, + { STB0899_DFLCSTM , 0x00 }, + { STB0899_DFLCSTL , 0x00 }, + { STB0899_SYNCCST , 0x00 }, + { STB0899_SYNCDCSTM , 0x00 }, + { STB0899_SYNCDCSTL , 0x00 }, + { STB0899_ISI_ENTRY , 0x00 }, + { STB0899_ISI_BIT_EN , 0x00 }, + { STB0899_MATSTRM , 0x00 }, + { STB0899_MATSTRL , 0x00 }, + { STB0899_UPLSTRM , 0x00 }, + { STB0899_UPLSTRL , 0x00 }, + { STB0899_DFLSTRM , 0x00 }, + { STB0899_DFLSTRL , 0x00 }, + { STB0899_SYNCSTR , 0x00 }, + { STB0899_SYNCDSTRM , 0x00 }, + { STB0899_SYNCDSTRL , 0x00 }, + { STB0899_CFGPDELSTATUS1 , 0x10 }, + { STB0899_CFGPDELSTATUS2 , 0x00 }, + { STB0899_BBFERRORM , 0x00 }, + { STB0899_BBFERRORL , 0x00 }, + { STB0899_UPKTERRORM , 0x00 }, + { STB0899_UPKTERRORL , 0x00 }, + { 0xffff , 0xff }, +}; + +struct stb0899_config vp1041_config = { + .init_dev = vp1041_stb0899_s1_init_1, + .init_s2_demod = stb0899_s2_init_2, + .init_s1_demod = vp1041_stb0899_s1_init_3, + .init_s2_fec = stb0899_s2_init_4, + .init_tst = stb0899_s1_init_5, + + .demod_address = 0x68, /* 0xd0 >> 1 */ + + .xtal_freq = 27000000, + .inversion = IQ_SWAP_ON, /* 1 */ + + .esno_ave = STB0899_DVBS2_ESNO_AVE, + .esno_quant = STB0899_DVBS2_ESNO_QUANT, + .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE, + .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE, + .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD, + .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ, + .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK, + .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF, + .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT, + + .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS, + .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET, + .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS, + .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER, + + .tuner_get_frequency = stb6100_get_frequency, + .tuner_set_frequency = stb6100_set_frequency, + .tuner_set_bandwidth = stb6100_set_bandwidth, + .tuner_get_bandwidth = stb6100_get_bandwidth, + .tuner_set_rfsiggain = NULL, +}; + +struct stb6100_config vp1041_stb6100_config = { + .tuner_address = 0x60, + .refclock = 27000000, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp1041.h b/drivers/media/dvb/mantis/mantis_vp1041.h new file mode 100644 index 00000000000..53f4cb18857 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1041.h @@ -0,0 +1,36 @@ +/* + Mantis VP-1041 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP1041_H +#define __MANTIS_VP1041_H + +#include "dvb_frontend.h" +#include "mantis_common.h" +#include "stb0899_drv.h" +#include "stb6100.h" +#include "lnbp21.h" + +#define MANTIS_VP_1041_DVB_S2 0x0031 + +extern struct mantis_hwconfig vp1041_mantis_config; +extern struct stb0899_config vp1041_config; +extern struct stb6100_config vp1041_stb6100_config; + +#endif // __MANTIS_VP1041_H -- cgit v1.2.3-70-g09d2 From 0131258ba7a5f776627da953b4cef775568026ea Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:44:55 -0300 Subject: V4L/DVB (13725): [Mantis/VP-1041] Revert to old register initialization parameters, for now. Thanks to eso46 for pointing it out Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_vp1041.c | 126 +++++++++++++++---------------- 1 file changed, 63 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index a3279f0e4b9..8854ef390e0 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -125,102 +125,102 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { { STB0899_DEMOD , 0x00 }, { STB0899_RCOMPC , 0xc9 }, - { STB0899_AGC1CN , 0x41 }, + { STB0899_AGC1CN , 0x01 }, { STB0899_AGC1REF , 0x10 }, - { STB0899_RTC , 0x7a }, + { STB0899_RTC , 0x23 }, { STB0899_TMGCFG , 0x4e }, { STB0899_AGC2REF , 0x34 }, { STB0899_TLSR , 0x84 }, - { STB0899_CFD , 0xc7 }, + { STB0899_CFD , 0xf7 }, { STB0899_ACLC , 0x87 }, { STB0899_BCLC , 0x94 }, { STB0899_EQON , 0x41 }, - { STB0899_LDT , 0xdd }, - { STB0899_LDT2 , 0xc9 }, + { STB0899_LDT , 0xf1 }, + { STB0899_LDT2 , 0xe3 }, { STB0899_EQUALREF , 0xb4 }, { STB0899_TMGRAMP , 0x10 }, { STB0899_TMGTHD , 0x30 }, - { STB0899_IDCCOMP , 0xfb }, - { STB0899_QDCCOMP , 0x03 }, - { STB0899_POWERI , 0x3b }, - { STB0899_POWERQ , 0x3d }, - { STB0899_RCOMP , 0x81 }, + { STB0899_IDCCOMP , 0xfd }, + { STB0899_QDCCOMP , 0xff }, + { STB0899_POWERI , 0x0c }, + { STB0899_POWERQ , 0x0f }, + { STB0899_RCOMP , 0x6c }, { STB0899_AGCIQIN , 0x80 }, - { STB0899_AGC2I1 , 0x04 }, - { STB0899_AGC2I2 , 0xf5 }, - { STB0899_TLIR , 0x25 }, - { STB0899_RTF , 0x80 }, + { STB0899_AGC2I1 , 0x06 }, + { STB0899_AGC2I2 , 0x00 }, + { STB0899_TLIR , 0x30 }, + { STB0899_RTF , 0x7f }, { STB0899_DSTATUS , 0x00 }, - { STB0899_LDI , 0xca }, - { STB0899_CFRM , 0xf1 }, - { STB0899_CFRL , 0xf3 }, - { STB0899_NIRM , 0x2a }, - { STB0899_NIRL , 0x05 }, - { STB0899_ISYMB , 0x17 }, - { STB0899_QSYMB , 0xfa }, + { STB0899_LDI , 0xbc }, + { STB0899_CFRM , 0xea }, + { STB0899_CFRL , 0x31 }, + { STB0899_NIRM , 0x2b }, + { STB0899_NIRL , 0x80 }, + { STB0899_ISYMB , 0x1d }, + { STB0899_QSYMB , 0xa6 }, { STB0899_SFRH , 0x2f }, { STB0899_SFRM , 0x68 }, { STB0899_SFRL , 0x40 }, { STB0899_SFRUPH , 0x2f }, { STB0899_SFRUPM , 0x68 }, { STB0899_SFRUPL , 0x40 }, - { STB0899_EQUAI1 , 0xfd }, - { STB0899_EQUAQ1 , 0x04 }, - { STB0899_EQUAI2 , 0x0f }, - { STB0899_EQUAQ2 , 0xff }, - { STB0899_EQUAI3 , 0xdf }, - { STB0899_EQUAQ3 , 0xfa }, - { STB0899_EQUAI4 , 0x37 }, - { STB0899_EQUAQ4 , 0x0d }, - { STB0899_EQUAI5 , 0xbd }, - { STB0899_EQUAQ5 , 0xf7 }, + { STB0899_EQUAI1 , 0x02 }, + { STB0899_EQUAQ1 , 0xff }, + { STB0899_EQUAI2 , 0x04 }, + { STB0899_EQUAQ2 , 0x05 }, + { STB0899_EQUAI3 , 0x02 }, + { STB0899_EQUAQ3 , 0xfd }, + { STB0899_EQUAI4 , 0x03 }, + { STB0899_EQUAQ4 , 0x07 }, + { STB0899_EQUAI5 , 0x08 }, + { STB0899_EQUAQ5 , 0xf5 }, { STB0899_DSTATUS2 , 0x00 }, { STB0899_VSTATUS , 0x00 }, - { STB0899_VERROR , 0xff }, + { STB0899_VERROR , 0x86 }, { STB0899_IQSWAP , 0x2a }, { STB0899_ECNT1M , 0x00 }, { STB0899_ECNT1L , 0x00 }, { STB0899_ECNT2M , 0x00 }, { STB0899_ECNT2L , 0x00 }, - { STB0899_ECNT3M , 0x00 }, - { STB0899_ECNT3L , 0x00 }, + { STB0899_ECNT3M , 0x0a }, + { STB0899_ECNT3L , 0xad }, { STB0899_FECAUTO1 , 0x06 }, { STB0899_FECM , 0x01 }, - { STB0899_VTH12 , 0xf0 }, - { STB0899_VTH23 , 0xa0 }, - { STB0899_VTH34 , 0x78 }, - { STB0899_VTH56 , 0x4e }, - { STB0899_VTH67 , 0x48 }, - { STB0899_VTH78 , 0x38 }, + { STB0899_VTH12 , 0xb0 }, + { STB0899_VTH23 , 0x7a }, + { STB0899_VTH34 , 0x58 }, + { STB0899_VTH56 , 0x38 }, + { STB0899_VTH67 , 0x34 }, + { STB0899_VTH78 , 0x24 }, { STB0899_PRVIT , 0xff }, { STB0899_VITSYNC , 0x19 }, { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ { STB0899_TSULC , 0x42 }, - { STB0899_RSLLC , 0x40 }, + { STB0899_RSLLC , 0x41 }, { STB0899_TSLPL , 0x12 }, { STB0899_TSCFGH , 0x0c }, { STB0899_TSCFGM , 0x00 }, - { STB0899_TSCFGL , 0x0c }, - { STB0899_TSOUT , 0x0d }, /* 0x0d for CAM */ + { STB0899_TSCFGL , 0x00 }, + { STB0899_TSOUT , 0x69 }, /* 0x0d for CAM */ { STB0899_RSSYNCDEL , 0x00 }, { STB0899_TSINHDELH , 0x02 }, { STB0899_TSINHDELM , 0x00 }, { STB0899_TSINHDELL , 0x00 }, - { STB0899_TSLLSTKM , 0x00 }, - { STB0899_TSLLSTKL , 0x00 }, + { STB0899_TSLLSTKM , 0x1b }, + { STB0899_TSLLSTKL , 0xb3 }, { STB0899_TSULSTKM , 0x00 }, - { STB0899_TSULSTKL , 0xab }, - { STB0899_PCKLENUL , 0x00 }, + { STB0899_TSULSTKL , 0x00 }, + { STB0899_PCKLENUL , 0xbc }, { STB0899_PCKLENLL , 0xcc }, - { STB0899_RSPCKLEN , 0xcc }, - { STB0899_TSSTATUS , 0x80 }, + { STB0899_RSPCKLEN , 0xbd }, + { STB0899_TSSTATUS , 0x90 }, { STB0899_ERRCTRL1 , 0xb6 }, - { STB0899_ERRCTRL2 , 0x96 }, - { STB0899_ERRCTRL3 , 0x89 }, + { STB0899_ERRCTRL2 , 0x95 }, + { STB0899_ERRCTRL3 , 0x8d }, { STB0899_DMONMSK1 , 0x27 }, { STB0899_DMONMSK0 , 0x03 }, { STB0899_DEMAPVIT , 0x5c }, - { STB0899_PLPARM , 0x1f }, + { STB0899_PLPARM , 0x19 }, { STB0899_PDELCTRL , 0x48 }, { STB0899_PDELCTRL2 , 0x00 }, { STB0899_BBHCTRL1 , 0x00 }, @@ -237,19 +237,19 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { { STB0899_SYNCDCSTL , 0x00 }, { STB0899_ISI_ENTRY , 0x00 }, { STB0899_ISI_BIT_EN , 0x00 }, - { STB0899_MATSTRM , 0x00 }, - { STB0899_MATSTRL , 0x00 }, - { STB0899_UPLSTRM , 0x00 }, - { STB0899_UPLSTRL , 0x00 }, - { STB0899_DFLSTRM , 0x00 }, + { STB0899_MATSTRM , 0xf0 }, + { STB0899_MATSTRL , 0x02 }, + { STB0899_UPLSTRM , 0x45 }, + { STB0899_UPLSTRL , 0x60 }, + { STB0899_DFLSTRM , 0xe3 }, { STB0899_DFLSTRL , 0x00 }, - { STB0899_SYNCSTR , 0x00 }, - { STB0899_SYNCDSTRM , 0x00 }, - { STB0899_SYNCDSTRL , 0x00 }, - { STB0899_CFGPDELSTATUS1 , 0x10 }, - { STB0899_CFGPDELSTATUS2 , 0x00 }, + { STB0899_SYNCSTR , 0x47 }, + { STB0899_SYNCDSTRM , 0x05 }, + { STB0899_SYNCDSTRL , 0x18 }, + { STB0899_CFGPDELSTATUS1 , 0x19 }, + { STB0899_CFGPDELSTATUS2 , 0x2b }, { STB0899_BBFERRORM , 0x00 }, - { STB0899_BBFERRORL , 0x00 }, + { STB0899_BBFERRORL , 0x01 }, { STB0899_UPKTERRORM , 0x00 }, { STB0899_UPKTERRORL , 0x00 }, { 0xffff , 0xff }, -- cgit v1.2.3-70-g09d2 From 35afca912ffb8ea5a060ff53a59266ccaa769c98 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:47:30 -0300 Subject: V4L/DVB (13726): [Mantis/Skystar HD2] Add support for the Technisat Skystar HD2 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 1 + drivers/media/dvb/mantis/mantis_dvb.c | 1 + drivers/media/dvb/mantis/mantis_vp1041.h | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 47cfb759f0b..a164bb14363 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -113,6 +113,7 @@ static void mantis_load_config(struct mantis_pci *mantis) mantis->hwconfig = &vp1034_mantis_config; break; case MANTIS_VP_1041_DVB_S2: // VP-1041 + case TECHNISAT_SKYSTAR_HD2: mantis->hwconfig = &vp1041_mantis_config; break; case MANTIS_VP_2033_DVB_C: // VP-2033 diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index a4750bb22b0..9634b972a0f 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -240,6 +240,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; case MANTIS_VP_1041_DVB_S2: + case TECHNISAT_SKYSTAR_HD2: mantis->fe = stb0899_attach(&vp1041_config, &mantis->adapter); if (mantis->fe) { dprintk(verbose, MANTIS_ERROR, 1, diff --git a/drivers/media/dvb/mantis/mantis_vp1041.h b/drivers/media/dvb/mantis/mantis_vp1041.h index 53f4cb18857..2cc83a6e599 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.h +++ b/drivers/media/dvb/mantis/mantis_vp1041.h @@ -28,6 +28,7 @@ #include "lnbp21.h" #define MANTIS_VP_1041_DVB_S2 0x0031 +#define TECHNISAT_SKYSTAR_HD2 0x0001 extern struct mantis_hwconfig vp1041_mantis_config; extern struct stb0899_config vp1041_config; -- cgit v1.2.3-70-g09d2 From 1159531a93f04346d94f72fdb4719c3f7e7d0a8c Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:48:03 -0300 Subject: V4L/DVB (13727): [Mantis/VP-1041] Bugfix: Sigh! Don't look for the STOP bit Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_vp1041.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 8854ef390e0..7dee1af0d64 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -64,7 +64,7 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { { STB0899_IRQMSK_0 , 0xff }, { STB0899_IRQCFG , 0x00 }, { STB0899_I2CCFG , 0x88 }, - { STB0899_I2CRPT , 0x5c }, + { STB0899_I2CRPT , 0x58 }, { STB0899_IOPVALUE5 , 0x00 }, { STB0899_IOPVALUE4 , 0x33 }, { STB0899_IOPVALUE3 , 0x6d }, -- cgit v1.2.3-70-g09d2 From 9ce39460837202920fb9bad88eeec13fc75e7a13 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:52:23 -0300 Subject: V4L/DVB (13728): [Mantis] Add in some Host Interface definitions Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.h | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_hif.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/dvb/mantis/mantis_hif.h new file mode 100644 index 00000000000..33b4f2b0ef6 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_hif.h @@ -0,0 +1,9 @@ +#ifndef __MANTIS_HIF_H +#define __MANTIS_HIF_H + +#define MANTIS_HIF_MEMRD 1 +#define MANTIS_HIF_MEMWR 2 +#define MANTIS_HIF_IOMRD 3 +#define MANTIS_HIF_IOMWR 4 + +#endif // __MANTIS_HIF_H -- cgit v1.2.3-70-g09d2 From 23fc1b2b00e849f6ec8628da77e2f282aedbebf3 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:53:07 -0300 Subject: V4L/DVB (13729): [Mantis] Add in a license header Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/dvb/mantis/mantis_hif.h index 33b4f2b0ef6..7ef45cec19d 100644 --- a/drivers/media/dvb/mantis/mantis_hif.h +++ b/drivers/media/dvb/mantis/mantis_hif.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_HIF_H #define __MANTIS_HIF_H -- cgit v1.2.3-70-g09d2 From cb428c3fe9667eb7521769f25f65b9dbf52a33ca Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:59:05 -0300 Subject: V4L/DVB (13730): [Mantis] Add in some UART definitions Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_uart.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_uart.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h new file mode 100644 index 00000000000..6c9a17c3bfb --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -0,0 +1,18 @@ +#ifndef __MANTIS_UART_H +#define __MANTIS_UART_H + +enum mantis_baud { + MANTIS_BAUD_9600 = 0, + MANTIS_BAUD_19200, + MANTIS_BAUD_38400, + MANTIS_BAUD_57600, + MANTIS_BAUD_115200 +}; + +enum mantis_parity { + MANTIS_PARITY_NONE = 0, + MANTIS_PARITY_EVEN, + MANTIS_PARITY_ODD +}; + +#endif // __MANTIS_UART_H -- cgit v1.2.3-70-g09d2 From d4f4ae046d2a9cd6b7ddb39e336a73ed92b63fe8 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:59:44 -0300 Subject: V4L/DVB (13731): [Mantis] Add in a license header Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_uart.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h index 6c9a17c3bfb..61138639c36 100644 --- a/drivers/media/dvb/mantis/mantis_uart.h +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_UART_H #define __MANTIS_UART_H -- cgit v1.2.3-70-g09d2 From dd827da1e7d6ecf81883af68731cf0f1c2393c6d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:00:30 -0300 Subject: V4L/DVB (13732): [Mantis] Add in some Link Layer definitions Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_link.h | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_link.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h new file mode 100644 index 00000000000..2849457c427 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -0,0 +1,51 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_LINK_H +#define __MANTIS_LINK_H + +enum mantis_sbuf_status { + MANTIS_SBUF_DATA_AVAIL = 1, + MANTIS_SBUF_DATA_EMPTY = 2, + MANTIS_SBUF_DATA_OVFLW = 3 +}; + +struct mantis_slot { + u32 timeout; +}; + +struct mantis_ca { + struct mantis_slot slot; + + struct tasklet_struct hif_evm_tasklet; + + u32 hif_event; + wait_queue_head_t hif_opdone_wq; + wait_queue_head_t hif_brrdyw_wq; + wait_queue_head_t hif_data_wq; + u32 hif_job_queue + + enum mantis_sbuf_status sbuf_status; + + struct dvb_device *ca_dev; + void *ca_priv; +}; + +#endif // __MANTIS_LINK_H -- cgit v1.2.3-70-g09d2 From bc4ed42fdf762a2049b255de92626ad1cfd86d8e Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:03:35 -0300 Subject: V4L/DVB (13733): [Mantis] Start with the PCMCIA interface Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 17 ++++++++-------- drivers/media/dvb/mantis/mantis_common.h | 4 ++++ drivers/media/dvb/mantis/mantis_link.h | 2 +- drivers/media/dvb/mantis/mantis_pcmcia.c | 34 ++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 drivers/media/dvb/mantis/mantis_pcmcia.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index bdf3e3629ab..fa9e806400e 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -1,11 +1,12 @@ -mantis-objs = mantis_core.o \ - mantis_dma.o \ - mantis_pci.o \ - mantis_i2c.o \ - mantis_dvb.o \ - mantis_vp1033.o \ - mantis_vp1034.o \ - mantis_vp1041.o \ +mantis-objs = mantis_core.o \ + mantis_dma.o \ + mantis_pci.o \ + mantis_i2c.o \ + mantis_dvb.o \ + mantis_pcmcia.o \ + mantis_vp1033.o \ + mantis_vp1034.o \ + mantis_vp1041.o \ mantis_vp2033.o \ mantis_vp2040.o \ mantis_vp3030.o diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 34d2389f312..24fc6da07fe 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -35,6 +35,8 @@ #include #include "mantis_reg.h" +#include "mantis_link.h" + #define MANTIS_ERROR 0 #define MANTIS_NOTICE 1 #define MANTIS_INFO 2 @@ -134,6 +136,8 @@ struct mantis_pci { /* A12 A13 A14 */ int gpio_status; + + struct mantis_ca *mantis_ca; }; extern unsigned int verbose; diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 2849457c427..2d9b64f6937 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -40,7 +40,7 @@ struct mantis_ca { wait_queue_head_t hif_opdone_wq; wait_queue_head_t hif_brrdyw_wq; wait_queue_head_t hif_data_wq; - u32 hif_job_queue + u32 hif_job_queue; enum mantis_sbuf_status sbuf_status; diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c new file mode 100644 index 00000000000..63f9621a90b --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -0,0 +1,34 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" + +int mantis_pcmcia_init(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + + return 0; +} + +void mantis_pcmcia_exit(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + +} -- cgit v1.2.3-70-g09d2 From d575571e8eda92c2cfd727ef050d17e30878fee6 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:04:18 -0300 Subject: V4L/DVB (13734): [Mantis] Initial go at an Event Manager Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 1 + drivers/media/dvb/mantis/mantis_common.h | 2 ++ drivers/media/dvb/mantis/mantis_evm.c | 37 ++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_evm.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index fa9e806400e..38d0e6dbafe 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -3,6 +3,7 @@ mantis-objs = mantis_core.o \ mantis_pci.o \ mantis_i2c.o \ mantis_dvb.o \ + mantis_evm.o \ mantis_pcmcia.o \ mantis_vp1033.o \ mantis_vp1034.o \ diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 24fc6da07fe..f9891ebcfb0 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -77,6 +77,8 @@ struct mantis_hwconfig { }; struct mantis_pci { + unsigned int verbose; + /* PCI stuff */ u16 vendor_id; u16 device_id; diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c new file mode 100644 index 00000000000..c9359d6ddc2 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -0,0 +1,37 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_link.h" + +int mantis_evmgr_init(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); + return 0; +} + +void mantis_evmgr_exit(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); +} -- cgit v1.2.3-70-g09d2 From fadfa070d30434dd228362c933827eb6ce137f2d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:05:19 -0300 Subject: V4L/DVB (13735): [Mantis] Implement the Event Manager tasklet Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 65 +++++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_reg.h | 58 ++++++++++++++++++++++++++++++- 2 files changed, 122 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index c9359d6ddc2..9f1740ea389 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -20,12 +20,76 @@ #include "mantis_common.h" #include "mantis_link.h" +#include "mantis_hif.h" + +void mantis_hifevm_tasklet(unsigned long data) +{ + struct mantis_ca *ca = (struct mantis_ca *) data; + struct mantis_pci *mantis = ca->ca_priv; + + u32 gpif_stat; + + gpif_stat = mmread(MANTIS_GPIF_STATUS); + + if (gpif_stat & MANTIS_GPIF_DETSTAT) { + if (gpif_stat & MANTIS_CARD_PLUGIN) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); + mmwrite(0xdada0000, MANTIS_CARD_RESET); + // Plugin call here + gpif_stat = 0; // crude ! + } + } else { + if (gpif_stat & MANTIS_CARD_PLUGOUT) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); + mmwrite(0xdada0000, MANTIS_CARD_RESET); + // Unplug call here + gpif_stat = 0; // crude ! + } + } + + if (gpif_stat & MANTIS_GPIF_EXTIRQ) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); + + if (gpif_stat & MANTIS_SBUF_WSTO) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); + + if (gpif_stat & MANTIS_GPIF_OTHERR) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); + + if (gpif_stat & MANTIS_SBUF_OVFLW) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); + + if (gpif_stat & MANTIS_GPIF_BRRDY) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); + ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; + if (ca->hif_job_queue & MANTIS_HIF_MEMRD) + wake_up(&ca->hif_brrdyw_wq); + } + if (gpif_stat & MANTIS_GPIF_WRACK) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); + + if (gpif_stat & MANTIS_GPIF_INTSTAT) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); + + if (gpif_stat & MANTIS_SBUF_EMPTY) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num); + + if (gpif_stat & MANTIS_SBUF_OPDONE) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); + if (ca->hif_job_queue) { + wake_up(&ca->hif_opdone_wq); + ca->hif_event = MANTIS_SBUF_OPDONE; + } + } +} int mantis_evmgr_init(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); + tasklet_init(&ca->hif_evm_tasklet, mantis_hifevm_tasklet, (unsigned long) ca); + return 0; } @@ -34,4 +98,5 @@ void mantis_evmgr_exit(struct mantis_ca *ca) struct mantis_pci *mantis = ca->ca_priv; dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); + tasklet_kill(&ca->hif_evm_tasklet); } diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h index 1b54e09fd86..d9862b7dbf0 100644 --- a/drivers/media/dvb/mantis/mantis_reg.h +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -73,6 +73,40 @@ #define MANTIS_I2C_STOP (0x01 << 5) #define MANTIS_I2C_PGMODE (0x01 << 3) +#define MANTIS_GPIF_CFGSLA 0x84 +#define MANTIS_GPIF_WAITSMPL (0x07 << 28) +#define MANTIS_GPIF_BYTEADDRSUB (0x01 << 25) +#define MANTIS_GPIF_WAITPOL (0x01 << 24) +#define MANTIS_GPIF_NCDELAY (0x07 << 20) +#define MANTIS_GPIF_RW2CSDELAY (0x07 << 16) +#define MANTIS_GPIF_SLFTIMEDMODE (0x01 << 15) +#define MANTIS_GPIF_SLFTIMEDDELY (0x7f << 8) +#define MANTIS_GPIF_DEVTYPE (0x07 << 4) +#define MANTIS_GPIF_BIGENDIAN (0x01 << 3) +#define MANTIS_GPIF_FETCHCMD (0x03 << 1) +#define MANTIS_GPIF_HWORDDEV (0x01 << 0) + +#define MANTIS_GPIF_WSTOPER 0x90 +#define MANTIS_GPIF_WSTOPERWREN3 (0x01 << 31) +#define MANTIS_GPIF_PARBOOTN (0x01 << 29) +#define MANTIS_GPIF_WSTOPERSLID3 (0x1f << 24) +#define MANTIS_GPIF_WSTOPERWREN2 (0x01 << 23) +#define MANTIS_GPIF_WSTOPERSLID2 (0x1f << 16) +#define MANTIS_GPIF_WSTOPERWREN1 (0x01 << 15) +#define MANTIS_GPIF_WSTOPERSLID1 (0x1f << 8) +#define MANTIS_GPIF_WSTOPERWREN0 (0x01 << 7) +#define MANTIS_GPIF_WSTOPERSLID0 (0x1f << 0) + +#define MANTIS_GPIF_CS2RW 0x94 +#define MANTIS_GPIF_CS2RWWREN3 (0x01 << 31) +#define MANTIS_GPIF_CS2RWDELY3 (0x3f << 24) +#define MANTIS_GPIF_CS2RWWREN2 (0x01 << 23) +#define MANTIS_GPIF_CS2RWDELY2 (0x3f << 16) +#define MANTIS_GPIF_CS2RWWREN1 (0x01 << 15) +#define MANTIS_GPIF_CS2RWDELY1 (0x3f << 8) +#define MANTIS_GPIF_CS2RWWREN0 (0x01 << 7) +#define MANTIS_GPIF_CS2RWDELY0 (0x3f << 0) + #define MANTIS_GPIF_IRQCFG 0x98 #define MANTIS_GPIF_IRQPOL (0x01 << 8) #define MANTIS_MASK_WRACK (0x01 << 7) @@ -99,11 +133,33 @@ #define MANTIS_CARD_PLUGIN (0x01 << 1) #define MANTIS_CARD_PLUGOUT (0x01 << 0) +#define MANTIS_GPIF_BRADDR 0xa0 +#define MANTIS_GPIF_PCMCIAREG (0x01 << 27) +#define MANTIS_GPIF_PCMCIAIOM (0x01 << 26) +#define MANTIS_GPIF_BR_ADDR (0xfffffff << 0) + +#define MANTIS_GPIF_BRBYTES 0xa4 +#define MANTIS_GPIF_BRCNT (0xfff << 0) + +#define MANTIS_PCMCIA_RESET 0xa8 +#define MANTIS_PCMCIA_RSTVAL (0xff << 0) + +#define MANTIS_CARD_RESET 0xac + #define MANTIS_GPIF_ADDR 0xb0 -#define MANTIS_GPIF_RDWRN (0x01 << 31) +#define MANTIS_GPIF_RDWRN (0x01 << 31) +#define MANTIS_GPIF_PCMCIAREG (0x01 << 27) +#define MANTIS_GPIF_PCMCIAIOM (0x01 << 26) +#define MANTIS_GPIF_HIF_ADDR (0xfffffff << 0) #define MANTIS_GPIF_DOUT 0xb4 +#define MANTIS_GPIF_HIF_DOUT (0xfffffff << 0) + #define MANTIS_GPIF_DIN 0xb8 +#define MANTIS_GPIF_HIF_DIN (0xfffffff << 0) +#define MANTIS_GPIF_SPARE 0xbc +#define MANTIS_GPIF_LOGICRD (0xffff << 16) +#define MANTIS_GPIF_LOGICRW (0xffff << 0) #endif //__MANTIS_REG_H -- cgit v1.2.3-70-g09d2 From 8ce571f5e7eb7186f676af3b60af7980c2fc7929 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:06:00 -0300 Subject: V4L/DVB (13736): [Mantis] Implement CAM Plug IN and Unplug events Sigh! how i wish things were simpler ... Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_link.h | 8 ++++ drivers/media/dvb/mantis/mantis_pcmcia.c | 66 ++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 2d9b64f6937..c6b32229edd 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -31,6 +31,12 @@ struct mantis_slot { u32 timeout; }; +/* Physical layer */ +enum mantis_slot_state { + MODULE_INSERTED = 3, + MODULE_XTRACTED = 4 +}; + struct mantis_ca { struct mantis_slot slot; @@ -44,6 +50,8 @@ struct mantis_ca { enum mantis_sbuf_status sbuf_status; + enum mantis_slot_state slot_state; + struct dvb_device *ca_dev; void *ca_priv; }; diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 63f9621a90b..960123f1ed4 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -19,11 +19,75 @@ */ #include "mantis_common.h" +#include "mantis_link.h" /* temporary due to physical layer stuff */ + +/* + * If Slot state is already PLUG_IN event and we are called + * again, definitely it is jitter alone + */ +void mantis_event_cam_plugin(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + + u32 gpif_irqcfg; + + if (ca->slot_state == MODULE_XTRACTED) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num); + udelay(50); + mmwrite(0xda000000, MANTIS_CARD_RESET); + gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); + gpif_irqcfg |= MANTIS_MASK_PLUGOUT; + gpif_irqcfg &= ~MANTIS_MASK_PLUGIN; + mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG); + udelay(500); + ca->slot_state = MODULE_INSERTED; + } + udelay(100); +} + +/* + * If Slot state is already UN_PLUG event and we are called + * again, definitely it is jitter alone + */ +void mantis_event_cam_unplug(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + + u32 gpif_irqcfg; + + if (ca->slot_state == MODULE_INSERTED) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num); + udelay(50); + mmwrite(0x00da0000, MANTIS_CARD_RESET); + gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); + gpif_irqcfg |= MANTIS_MASK_PLUGIN; + gpif_irqcfg &= ~MANTIS_MASK_PLUGOUT; + mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG); + udelay(500); + ca->slot_state = MODULE_XTRACTED; + } + udelay(100); +} int mantis_pcmcia_init(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; + u32 gpif_stat, card_stat; + + gpif_stat = mmread(MANTIS_GPIF_STATUS); + card_stat = mmread(MANTIS_GPIF_IRQCFG); + + if (gpif_stat & MANTIS_GPIF_DETSTAT) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); + mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG); + ca->slot_state = MODULE_INSERTED; + } else { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); + mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG); + ca->slot_state = MODULE_XTRACTED; + } + return 0; } @@ -31,4 +95,6 @@ void mantis_pcmcia_exit(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; + mmwrite(mmread(MANTIS_GPIF_STATUS) & (~MANTIS_CARD_PLUGOUT | ~MANTIS_CARD_PLUGIN), MANTIS_GPIF_STATUS); + mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ0, MANTIS_INT_MASK); } -- cgit v1.2.3-70-g09d2 From 50d82602760c99d2c954c33360990c00146532cd Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:06:38 -0300 Subject: V4L/DVB (13737): [Mantis] Register the CA device, dummy functions for now Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 1 + drivers/media/dvb/mantis/mantis_ca.c | 127 +++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_evm.c | 4 ++ drivers/media/dvb/mantis/mantis_link.h | 8 +++ 4 files changed, 140 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_ca.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index 38d0e6dbafe..c4da0d8ed18 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -4,6 +4,7 @@ mantis-objs = mantis_core.o \ mantis_i2c.o \ mantis_dvb.o \ mantis_evm.o \ + mantis_ca.o \ mantis_pcmcia.o \ mantis_vp1033.o \ mantis_vp1034.o \ diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c new file mode 100644 index 00000000000..6e440d31b79 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -0,0 +1,127 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_link.h" +#include "mantis_hif.h" + + +static int mantis_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long parg) +{ + return 0; +} + +static int mantis_ca_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int mantis_ca_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t mantis_ca_read(struct file *file, char __user *buffer, size_t count, loff_t *ofset) +{ + struct dvb_device *dvbdev = file->private_data; + struct mantis_ca *ca = dvbdev->priv; + + int status; + + return 0; +error: + return status; +} + +static ssize_t mantis_ca_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset) +{ + struct dvb_device *dvbdev = file->private_data; + struct mantis_ca *ca = dvbdev->priv; + + int status; + + return 0; +error: + return status; +} + +static struct file_operations mantis_fops = { + .owner = THIS_MODULE, + .ioctl = mantis_ca_ioctl, + .open = mantis_ca_open, + .release = mantis_ca_release, + .read = mantis_ca_read, + .write = mantis_ca_write, +}; + +static struct dvb_device mantis_ca = { + .priv = NULL, + .users = 1, + .readers = 1, + .writers = 1, + .fops = &mantis_fops, +}; + +struct dvb_device *mantis_ca_init(struct mantis_pci *mantis) +{ + int ret; + + struct dvb_device *dvbdev; + struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter; + struct mantis_ca *ca; + + if (!(ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL))) { + dprintk(verbose, MANTIS_ERROR, 1, "Out of memory!, exiting .."); + return NULL; + } + + ca->ca_priv = mantis; + mantis->mantis_ca = ca; + mantis_evmgr_init(ca); + + dprintk(verbose, MANTIS_ERROR, 0, "CA: Registering Mantis Adapter(%d) Slot(0)\n", mantis->num); + if (dvb_register_device(dvb_adapter, &dvbdev, &mantis_ca, ca, DVB_DEVICE_CA) == 0) { + ca->ca_dev = dvbdev; + return ca->ca_dev; + } + return 0; + +error: + if (ca != NULL) { + dprintk(verbose, MANTIS_ERROR, 1, "Error .."); + if (ca->ca_dev != NULL) + dvb_unregister_device(ca->ca_dev); + + kfree(ca); + } + return NULL; +} + +void mantis_ca_exit(struct mantis_pci *mantis) +{ + struct mantis_ca *ca = mantis->mantis_ca; + + mantis_evmgr_exit(ca); + dprintk(verbose, MANTIS_ERROR, 0, "CA: Unregister Mantis Adapter(%d) Slot(0)\n", mantis->num); + if (ca->ca_dev) + dvb_unregister_device(ca->ca_dev); + + kfree(ca); +} diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 9f1740ea389..c4a1c89431e 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -90,6 +90,8 @@ int mantis_evmgr_init(struct mantis_ca *ca) dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); tasklet_init(&ca->hif_evm_tasklet, mantis_hifevm_tasklet, (unsigned long) ca); + mantis_pcmcia_init(ca); + return 0; } @@ -99,4 +101,6 @@ void mantis_evmgr_exit(struct mantis_ca *ca) dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); tasklet_kill(&ca->hif_evm_tasklet); + + mantis_pcmcia_exit(ca); } diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index c6b32229edd..a45dd7185e0 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -56,4 +56,12 @@ struct mantis_ca { void *ca_priv; }; +/* CA */ +extern void mantis_event_cam_plugin(struct mantis_ca *ca); +extern void mantis_event_cam_unplug(struct mantis_ca *ca); +extern int mantis_pcmcia_init(struct mantis_ca *ca); +extern void mantis_pcmcia_exit(struct mantis_ca *ca); +extern int mantis_evmgr_init(struct mantis_ca *ca); +extern void mantis_evmgr_exit(struct mantis_ca *ca); + #endif // __MANTIS_LINK_H -- cgit v1.2.3-70-g09d2 From d9dd5f7168d6a61491996fc02e4deb9d96308178 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:07:41 -0300 Subject: V4L/DVB (13738): [Mantis] Enable IRQ0 events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 4 ++-- drivers/media/dvb/mantis/mantis_dvb.c | 2 ++ drivers/media/dvb/mantis/mantis_evm.c | 26 +++++++++++++------------- drivers/media/dvb/mantis/mantis_pci.c | 10 ++++------ drivers/media/dvb/mantis/mantis_pcmcia.c | 9 +++++---- 5 files changed, 26 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 6e440d31b79..e6de3c9d3ce 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -93,12 +93,12 @@ struct dvb_device *mantis_ca_init(struct mantis_pci *mantis) } ca->ca_priv = mantis; - mantis->mantis_ca = ca; - mantis_evmgr_init(ca); dprintk(verbose, MANTIS_ERROR, 0, "CA: Registering Mantis Adapter(%d) Slot(0)\n", mantis->num); if (dvb_register_device(dvb_adapter, &dvbdev, &mantis_ca, ca, DVB_DEVICE_CA) == 0) { ca->ca_dev = dvbdev; + mantis->mantis_ca = ca; + mantis_evmgr_init(ca); return ca->ca_dev; } return 0; diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 9634b972a0f..3325b59ce19 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -190,6 +190,8 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); mantis_frontend_init(mantis); + mantis_ca_init(mantis); + return 0; /* Error conditions .. */ diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index c4a1c89431e..d81068d0834 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -33,14 +33,14 @@ void mantis_hifevm_tasklet(unsigned long data) if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); // Plugin call here gpif_stat = 0; // crude ! } } else { if (gpif_stat & MANTIS_CARD_PLUGOUT) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); // Unplug call here gpif_stat = 0; // crude ! @@ -48,34 +48,34 @@ void mantis_hifevm_tasklet(unsigned long data) } if (gpif_stat & MANTIS_GPIF_EXTIRQ) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); if (gpif_stat & MANTIS_SBUF_WSTO) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); if (gpif_stat & MANTIS_GPIF_OTHERR) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); if (gpif_stat & MANTIS_SBUF_OVFLW) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); if (gpif_stat & MANTIS_GPIF_BRRDY) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; if (ca->hif_job_queue & MANTIS_HIF_MEMRD) wake_up(&ca->hif_brrdyw_wq); } if (gpif_stat & MANTIS_GPIF_WRACK) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); if (gpif_stat & MANTIS_GPIF_INTSTAT) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); if (gpif_stat & MANTIS_SBUF_EMPTY) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num); if (gpif_stat & MANTIS_SBUF_OPDONE) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); if (ca->hif_job_queue) { wake_up(&ca->hif_opdone_wq); ca->hif_event = MANTIS_SBUF_OPDONE; @@ -87,7 +87,7 @@ int mantis_evmgr_init(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); + dprintk(verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); tasklet_init(&ca->hif_evm_tasklet, mantis_hifevm_tasklet, (unsigned long) ca); mantis_pcmcia_init(ca); @@ -99,7 +99,7 @@ void mantis_evmgr_exit(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); tasklet_kill(&ca->hif_evm_tasklet); mantis_pcmcia_exit(ca); diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 402f866e12d..814c6ace3d3 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -54,12 +54,15 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) { u32 stat = 0, mask = 0, lstat = 0, mstat = 0; struct mantis_pci *mantis; + struct mantis_ca *ca; mantis = (struct mantis_pci *) dev_id; if (unlikely(mantis == NULL)) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis == NULL"); return IRQ_NONE; } + ca = mantis->mantis_ca; + stat = mmread(MANTIS_INT_STAT); mask = mmread(MANTIS_INT_MASK); mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; @@ -72,14 +75,9 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) if (stat & MANTIS_INT_RISCEN) { dprintk(verbose, MANTIS_DEBUG, 0, "* DMA enabl *"); } - if (stat & MANTIS_INT_I2CRACK) { - dprintk(verbose, MANTIS_DEBUG, 0, "* I2C R-ACK *"); - } - if (stat & MANTIS_INT_PCMCIA7) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-07 *"); - } if (stat & MANTIS_INT_IRQ0) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); + tasklet_schedule(&ca->hif_evm_tasklet); } if (stat & MANTIS_INT_IRQ1) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 960123f1ed4..47cc720d35d 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -32,7 +32,7 @@ void mantis_event_cam_plugin(struct mantis_ca *ca) u32 gpif_irqcfg; if (ca->slot_state == MODULE_XTRACTED) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num); udelay(50); mmwrite(0xda000000, MANTIS_CARD_RESET); gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); @@ -56,7 +56,7 @@ void mantis_event_cam_unplug(struct mantis_ca *ca) u32 gpif_irqcfg; if (ca->slot_state == MODULE_INSERTED) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num); udelay(50); mmwrite(0x00da0000, MANTIS_CARD_RESET); gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); @@ -75,15 +75,16 @@ int mantis_pcmcia_init(struct mantis_ca *ca) u32 gpif_stat, card_stat; + mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ0, MANTIS_INT_MASK); gpif_stat = mmread(MANTIS_GPIF_STATUS); card_stat = mmread(MANTIS_GPIF_IRQCFG); if (gpif_stat & MANTIS_GPIF_DETSTAT) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_INSERTED; } else { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_XTRACTED; } -- cgit v1.2.3-70-g09d2 From 3062b1571a1d3520c4d3160ebbfca8002b1d6963 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:08:25 -0300 Subject: V4L/DVB (13739): [Mantis] Event Manager: Handle Masked events only Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 1 + drivers/media/dvb/mantis/mantis_evm.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 3325b59ce19..ade444963c8 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -313,6 +313,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) int __devexit mantis_dvb_exit(struct mantis_pci *mantis) { + mantis_ca_exit(mantis); tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index d81068d0834..c35ddd868f8 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -27,9 +27,12 @@ void mantis_hifevm_tasklet(unsigned long data) struct mantis_ca *ca = (struct mantis_ca *) data; struct mantis_pci *mantis = ca->ca_priv; - u32 gpif_stat; + u32 gpif_stat, gpif_mask; gpif_stat = mmread(MANTIS_GPIF_STATUS); + gpif_mask = mmread(MANTIS_GPIF_IRQCFG); + if (!((gpif_stat & 0xff) & (gpif_mask & 0xff))) + return; if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { -- cgit v1.2.3-70-g09d2 From 12855cac87218d0c92ffdebb7270cec040cf5a6a Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:09:04 -0300 Subject: V4L/DVB (13740): [Mantis] Schedule the work instead of handling the task directly Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 4 ++++ drivers/media/dvb/mantis/mantis_evm.c | 17 +++++++---------- drivers/media/dvb/mantis/mantis_link.h | 4 +++- drivers/media/dvb/mantis/mantis_pci.c | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index f9891ebcfb0..7f1cfad7488 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -151,4 +151,8 @@ extern int mantis_dvb_exit(struct mantis_pci *mantis); extern void mantis_dma_xfer(unsigned long data); extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); +extern struct dvb_device *mantis_ca_init(struct mantis_pci *mantis); +extern void mantis_ca_exit(struct mantis_pci *mantis); + + #endif //__MANTIS_COMMON_H diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index c35ddd868f8..74514839998 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -22,9 +22,9 @@ #include "mantis_link.h" #include "mantis_hif.h" -void mantis_hifevm_tasklet(unsigned long data) +static void mantis_hifevm_work(struct work_struct *work) { - struct mantis_ca *ca = (struct mantis_ca *) data; + struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work); struct mantis_pci *mantis = ca->ca_priv; u32 gpif_stat, gpif_mask; @@ -38,15 +38,13 @@ void mantis_hifevm_tasklet(unsigned long data) if (gpif_stat & MANTIS_CARD_PLUGIN) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); - // Plugin call here - gpif_stat = 0; // crude ! + mantis_event_cam_plugin(ca); } } else { if (gpif_stat & MANTIS_CARD_PLUGOUT) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); - // Unplug call here - gpif_stat = 0; // crude ! + mantis_event_cam_unplug(ca); } } @@ -91,9 +89,9 @@ int mantis_evmgr_init(struct mantis_ca *ca) struct mantis_pci *mantis = ca->ca_priv; dprintk(verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); - tasklet_init(&ca->hif_evm_tasklet, mantis_hifevm_tasklet, (unsigned long) ca); - + INIT_WORK(&ca->hif_evm_work, mantis_hifevm_work); mantis_pcmcia_init(ca); + schedule_work(&ca->hif_evm_work); return 0; } @@ -103,7 +101,6 @@ void mantis_evmgr_exit(struct mantis_ca *ca) struct mantis_pci *mantis = ca->ca_priv; dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); - tasklet_kill(&ca->hif_evm_tasklet); - + flush_scheduled_work(); mantis_pcmcia_exit(ca); } diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index a45dd7185e0..33b39b781d2 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -21,6 +21,8 @@ #ifndef __MANTIS_LINK_H #define __MANTIS_LINK_H +#include + enum mantis_sbuf_status { MANTIS_SBUF_DATA_AVAIL = 1, MANTIS_SBUF_DATA_EMPTY = 2, @@ -40,7 +42,7 @@ enum mantis_slot_state { struct mantis_ca { struct mantis_slot slot; - struct tasklet_struct hif_evm_tasklet; + struct work_struct hif_evm_work; u32 hif_event; wait_queue_head_t hif_opdone_wq; diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 814c6ace3d3..6eecd54a445 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -77,7 +77,7 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) } if (stat & MANTIS_INT_IRQ0) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); - tasklet_schedule(&ca->hif_evm_tasklet); + schedule_work(&ca->hif_evm_work); } if (stat & MANTIS_INT_IRQ1) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); -- cgit v1.2.3-70-g09d2 From d8b14f8a76d71c84622a211f57baf15f61cc9703 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:09:47 -0300 Subject: V4L/DVB (13741): [Mantis] Implement HIF Mem Read/Write operations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 1 + drivers/media/dvb/mantis/mantis_dma.c | 4 +- drivers/media/dvb/mantis/mantis_evm.c | 3 +- drivers/media/dvb/mantis/mantis_hif.c | 139 +++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_link.h | 10 ++- drivers/media/dvb/mantis/mantis_reg.h | 8 +- 6 files changed, 157 insertions(+), 8 deletions(-) create mode 100644 drivers/media/dvb/mantis/mantis_hif.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index c4da0d8ed18..d002ef9f744 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -4,6 +4,7 @@ mantis-objs = mantis_core.o \ mantis_i2c.o \ mantis_dvb.o \ mantis_evm.o \ + mantis_hif.o \ mantis_ca.o \ mantis_pcmcia.o \ mantis_vp1033.o \ diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index f685992f7d0..250f49a913a 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -190,7 +190,7 @@ void mantis_dma_start(struct mantis_pci *mantis) mantis_risc_program(mantis); mmwrite(mantis->risc_dma, MANTIS_RISC_START); - mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); + mmwrite(mmread(MANTIS_GPIF_HIFADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_HIFADDR); mmwrite(0, MANTIS_DMA_CTL); mantis->last_block = mantis->finished_block = 0; @@ -210,7 +210,7 @@ void mantis_dma_stop(struct mantis_pci *mantis) mask = mmread(MANTIS_INT_MASK); dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); - mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_RDWRN))), MANTIS_GPIF_ADDR); + mmwrite((mmread(MANTIS_GPIF_HIFADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_HIFADDR); mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | MANTIS_DCAP_EN | diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 74514839998..dbcdca3a8f0 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -92,7 +92,7 @@ int mantis_evmgr_init(struct mantis_ca *ca) INIT_WORK(&ca->hif_evm_work, mantis_hifevm_work); mantis_pcmcia_init(ca); schedule_work(&ca->hif_evm_work); - + mantis_hif_init(ca); return 0; } @@ -102,5 +102,6 @@ void mantis_evmgr_exit(struct mantis_ca *ca) dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); flush_scheduled_work(); + mantis_hif_exit(ca); mantis_pcmcia_exit(ca); } diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c new file mode 100644 index 00000000000..1472008e257 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -0,0 +1,139 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_hif.h" +#include "mantis_link.h" /* temporary due to physical layer stuff */ + +static int mantis_hif_data_available(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + int rc = 0; + + if (wait_event_interruptible_timeout(ca->hif_data_wq, + ca->sbuf_status & MANTIS_SBUF_DATA_AVAIL, + msecs_to_jiffies(500)) == -ERESTARTSYS) { + + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Read wait event timeout !", mantis->num); + rc = -EREMOTEIO; + } + ca->sbuf_status &= ~MANTIS_SBUF_DATA_AVAIL; + udelay(2); + return rc; +} + +static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + int rc = 0; + + if (wait_event_interruptible_timeout(ca->hif_opdone_wq, + ca->hif_event & MANTIS_SBUF_OPDONE, + msecs_to_jiffies(500)) == -ERESTARTSYS) { + + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num); + rc = -EREMOTEIO; + } + ca->hif_event &= ~MANTIS_SBUF_OPDONE; + udelay(5); + return rc; +} + +int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 hif_addr = 0, data, count = 4; + + hif_addr |= MANTIS_GPIF_HIFRDWRN; + hif_addr &= ~MANTIS_GPIF_PCMCIAREG; + hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; + hif_addr |= addr; + + mmwrite(hif_addr, MANTIS_GPIF_BRADDR); + mmwrite(count, MANTIS_GPIF_BRBYTES); + + udelay(20); + + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + if (mantis_hif_data_available(ca) != 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer burst read failed", mantis->num); + return -EREMOTEIO; + } + if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); + return -EREMOTEIO; + } + data = mmread(MANTIS_GPIF_HIFDIN); + + return (data >> 24) & 0xff; +} + +int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) +{ + struct mantis_slot *slot = ca->slot; + struct mantis_pci *mantis = ca->ca_priv; + u32 hif_addr = 0; + + hif_addr &= ~MANTIS_GPIF_HIFRDWRN; + hif_addr &= ~MANTIS_GPIF_PCMCIAREG; + hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; + hif_addr |= addr; + + mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */ + + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(data, MANTIS_GPIF_HIFDOUT); + ca->hif_job_queue = MANTIS_HIF_MEMWR; + + if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + ca->hif_job_queue &= ~MANTIS_HIF_MEMWR; + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + return -EREMOTEIO; + } + ca->hif_job_queue &= ~MANTIS_HIF_MEMWR; + return 0; +} + +int mantis_hif_init(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 irqcfg; + + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); + init_waitqueue_head(&ca->hif_data_wq); + init_waitqueue_head(&ca->hif_opdone_wq); + + irqcfg = mmread(MANTIS_GPIF_IRQCFG); + irqcfg |= MANTIS_MASK_BRRDY; + mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); + + return 0; +} + +void mantis_hif_exit(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 irqcfg; + + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num); + irqcfg = mmread(MANTIS_GPIF_IRQCFG); + irqcfg &= ~MANTIS_MASK_BRRDY; + mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); +} diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 33b39b781d2..8862502866c 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -31,6 +31,8 @@ enum mantis_sbuf_status { struct mantis_slot { u32 timeout; + u32 slave_cfg; + u32 bar; }; /* Physical layer */ @@ -40,7 +42,7 @@ enum mantis_slot_state { }; struct mantis_ca { - struct mantis_slot slot; + struct mantis_slot slot[4]; struct work_struct hif_evm_work; @@ -66,4 +68,10 @@ extern void mantis_pcmcia_exit(struct mantis_ca *ca); extern int mantis_evmgr_init(struct mantis_ca *ca); extern void mantis_evmgr_exit(struct mantis_ca *ca); +/* HIF */ +extern int mantis_hif_init(struct mantis_ca *ca); +extern void mantis_hif_exit(struct mantis_ca *ca); +extern int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr); +extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data); + #endif // __MANTIS_LINK_H diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h index d9862b7dbf0..6f5cd493676 100644 --- a/drivers/media/dvb/mantis/mantis_reg.h +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -147,16 +147,16 @@ #define MANTIS_CARD_RESET 0xac #define MANTIS_GPIF_ADDR 0xb0 -#define MANTIS_GPIF_RDWRN (0x01 << 31) +#define MANTIS_GPIF_HIFRDWRN (0x01 << 31) #define MANTIS_GPIF_PCMCIAREG (0x01 << 27) #define MANTIS_GPIF_PCMCIAIOM (0x01 << 26) -#define MANTIS_GPIF_HIF_ADDR (0xfffffff << 0) +#define MANTIS_GPIF_HIFADDR (0xfffffff << 0) #define MANTIS_GPIF_DOUT 0xb4 -#define MANTIS_GPIF_HIF_DOUT (0xfffffff << 0) +#define MANTIS_GPIF_HIFDOUT (0xfffffff << 0) #define MANTIS_GPIF_DIN 0xb8 -#define MANTIS_GPIF_HIF_DIN (0xfffffff << 0) +#define MANTIS_GPIF_HIFDIN (0xfffffff << 0) #define MANTIS_GPIF_SPARE 0xbc #define MANTIS_GPIF_LOGICRD (0xffff << 16) -- cgit v1.2.3-70-g09d2 From c9a750c909cbde15ecd0f8545f48e051bfee6271 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:10:25 -0300 Subject: V4L/DVB (13742): [Mantis] Implement PCMCIA I/O Rd/Wr operations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 54 ++++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_link.h | 2 ++ 2 files changed, 56 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 1472008e257..42aedf7a014 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -111,6 +111,60 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) return 0; } +int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr, u32 count, u32 *data) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 hif_addr = 0; + + hif_addr &= ~MANTIS_GPIF_PCMCIAREG; + hif_addr |= MANTIS_GPIF_HIFRDWRN; + hif_addr |= MANTIS_GPIF_PCMCIAIOM; + hif_addr |= addr; + + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + ca->hif_job_queue = MANTIS_HIF_IOMRD; + + if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + return -EREMOTEIO; + } + udelay(50); + ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; + *data = mmread(MANTIS_GPIF_HIFDIN); + hif_addr |= MANTIS_GPIF_PCMCIAREG; + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + + return 0; +} + +int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u32 data) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 hif_addr = 0; + + hif_addr &= ~MANTIS_GPIF_PCMCIAREG; + hif_addr &= ~MANTIS_GPIF_HIFRDWRN; + hif_addr |= MANTIS_GPIF_PCMCIAIOM; + hif_addr |= addr; + + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(data, MANTIS_GPIF_HIFDOUT); + + ca->hif_job_queue = MANTIS_HIF_IOMWR; + if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + return -EREMOTEIO; + } + udelay(50); + ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; + hif_addr |= MANTIS_GPIF_PCMCIAREG; + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + + return 0; +} + int mantis_hif_init(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 8862502866c..478900ea184 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -73,5 +73,7 @@ extern int mantis_hif_init(struct mantis_ca *ca); extern void mantis_hif_exit(struct mantis_ca *ca); extern int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr); extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data); +extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr, u32 count, u32 *data); +extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u32 data); #endif // __MANTIS_LINK_H -- cgit v1.2.3-70-g09d2 From 6053240f5cc914d40ac9c7afe15008bf3e46359c Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:11:14 -0300 Subject: V4L/DVB (13743): [Mantis CA] Use DVB_CA Tuple parser Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 129 ++++++++++++++++--------------- drivers/media/dvb/mantis/mantis_common.h | 2 +- drivers/media/dvb/mantis/mantis_hif.c | 10 +-- drivers/media/dvb/mantis/mantis_link.h | 9 ++- 4 files changed, 80 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index e6de3c9d3ce..4be61ca02c2 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -22,96 +22,104 @@ #include "mantis_link.h" #include "mantis_hif.h" - -static int mantis_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long parg) +static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr) { - return 0; + struct mantis_ca *ca = en50221->data; + + if (slot != 0) + return -EINVAL; + + return mantis_hif_read_mem(ca, addr); } -static int mantis_ca_open(struct inode *inode, struct file *file) +static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data) { - return 0; + struct mantis_ca *ca = en50221->data; + + if (slot != 0) + return -EINVAL; + + return mantis_hif_write_mem(ca, addr, data); } -static int mantis_ca_release(struct inode *inode, struct file *file) +static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr) { - return 0; + struct mantis_ca *ca = en50221->data; + + if (slot != 0) + return -EINVAL; + + return mantis_hif_read_iom(ca, addr); } -static ssize_t mantis_ca_read(struct file *file, char __user *buffer, size_t count, loff_t *ofset) +static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data) { - struct dvb_device *dvbdev = file->private_data; - struct mantis_ca *ca = dvbdev->priv; + struct mantis_ca *ca = en50221->data; - int status; + if (slot != 0) + return -EINVAL; - return 0; -error: - return status; + return mantis_hif_write_iom(ca, addr, data); } -static ssize_t mantis_ca_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset) +static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) { - struct dvb_device *dvbdev = file->private_data; - struct mantis_ca *ca = dvbdev->priv; + return 0; +} - int status; +static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) +{ + return 0; +} +static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) +{ return 0; -error: - return status; } -static struct file_operations mantis_fops = { - .owner = THIS_MODULE, - .ioctl = mantis_ca_ioctl, - .open = mantis_ca_open, - .release = mantis_ca_release, - .read = mantis_ca_read, - .write = mantis_ca_write, -}; - -static struct dvb_device mantis_ca = { - .priv = NULL, - .users = 1, - .readers = 1, - .writers = 1, - .fops = &mantis_fops, -}; - -struct dvb_device *mantis_ca_init(struct mantis_pci *mantis) +static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open) { - int ret; + return 0; +} - struct dvb_device *dvbdev; +int mantis_ca_init(struct mantis_pci *mantis) +{ struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter; struct mantis_ca *ca; + int ca_flags = 0, result; if (!(ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL))) { dprintk(verbose, MANTIS_ERROR, 1, "Out of memory!, exiting .."); - return NULL; + result = -ENOMEM; + goto err; } ca->ca_priv = mantis; - - dprintk(verbose, MANTIS_ERROR, 0, "CA: Registering Mantis Adapter(%d) Slot(0)\n", mantis->num); - if (dvb_register_device(dvb_adapter, &dvbdev, &mantis_ca, ca, DVB_DEVICE_CA) == 0) { - ca->ca_dev = dvbdev; - mantis->mantis_ca = ca; - mantis_evmgr_init(ca); - return ca->ca_dev; + mantis->mantis_ca = ca; + + /* register CA interface */ + ca->en50221.owner = THIS_MODULE; + ca->en50221.read_attribute_mem = mantis_ca_read_attr_mem; + ca->en50221.write_attribute_mem = mantis_ca_write_attr_mem; + ca->en50221.read_cam_control = mantis_ca_read_cam_ctl; + ca->en50221.write_cam_control = mantis_ca_write_cam_ctl; + ca->en50221.slot_reset = mantis_ca_slot_reset; + ca->en50221.slot_shutdown = mantis_ca_slot_shutdown; + ca->en50221.slot_ts_enable = mantis_ts_control; + ca->en50221.poll_slot_status = mantis_slot_status; + ca->en50221.data = ca; + + dprintk(verbose, MANTIS_ERROR, 1, "Registering EN50221 device"); + if ((result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1)) != 0) { + dprintk(verbose, MANTIS_ERROR, 1, "EN50221: Initialization failed"); + goto err; } + dprintk(verbose, MANTIS_ERROR, 1, "Registered EN50221 device"); + mantis_evmgr_init(ca); return 0; - -error: - if (ca != NULL) { - dprintk(verbose, MANTIS_ERROR, 1, "Error .."); - if (ca->ca_dev != NULL) - dvb_unregister_device(ca->ca_dev); - - kfree(ca); - } - return NULL; +err: + kfree(ca); + return result; } void mantis_ca_exit(struct mantis_pci *mantis) @@ -119,9 +127,8 @@ void mantis_ca_exit(struct mantis_pci *mantis) struct mantis_ca *ca = mantis->mantis_ca; mantis_evmgr_exit(ca); - dprintk(verbose, MANTIS_ERROR, 0, "CA: Unregister Mantis Adapter(%d) Slot(0)\n", mantis->num); - if (ca->ca_dev) - dvb_unregister_device(ca->ca_dev); + dprintk(verbose, MANTIS_ERROR, 1, "Unregistering EN50221 device"); + dvb_ca_en50221_release(&ca->en50221); kfree(ca); } diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 7f1cfad7488..0aa4001dea9 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -151,7 +151,7 @@ extern int mantis_dvb_exit(struct mantis_pci *mantis); extern void mantis_dma_xfer(unsigned long data); extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); -extern struct dvb_device *mantis_ca_init(struct mantis_pci *mantis); +extern int mantis_ca_init(struct mantis_pci *mantis); extern void mantis_ca_exit(struct mantis_pci *mantis); diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 42aedf7a014..6a1ea96c16d 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -111,10 +111,10 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) return 0; } -int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr, u32 count, u32 *data) +int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) { struct mantis_pci *mantis = ca->ca_priv; - u32 hif_addr = 0; + u32 data, hif_addr = 0; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr |= MANTIS_GPIF_HIFRDWRN; @@ -131,14 +131,14 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr, u32 count, u32 *data) } udelay(50); ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; - *data = mmread(MANTIS_GPIF_HIFDIN); + data = mmread(MANTIS_GPIF_HIFDIN); hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); - return 0; + return data; } -int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u32 data) +int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) { struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0; diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 478900ea184..23ff2d6aadb 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -22,6 +22,7 @@ #define __MANTIS_LINK_H #include +#include "dvb_ca_en50221.h" enum mantis_sbuf_status { MANTIS_SBUF_DATA_AVAIL = 1, @@ -56,8 +57,10 @@ struct mantis_ca { enum mantis_slot_state slot_state; - struct dvb_device *ca_dev; +// struct dvb_device *ca_dev; void *ca_priv; + + struct dvb_ca_en50221 en50221; }; /* CA */ @@ -73,7 +76,7 @@ extern int mantis_hif_init(struct mantis_ca *ca); extern void mantis_hif_exit(struct mantis_ca *ca); extern int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr); extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data); -extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr, u32 count, u32 *data); -extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u32 data); +extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr); +extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data); #endif // __MANTIS_LINK_H -- cgit v1.2.3-70-g09d2 From 4e9fbeeedc22d287b5d05e32bbc647cd2dc8c663 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:11:41 -0300 Subject: V4L/DVB (13744): [Mantis CA] Use Module status to signal Slot events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 4be61ca02c2..cd6bed73729 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -79,6 +79,11 @@ static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open) { + struct mantis_ca *ca = en50221->data; + + if (ca->slot_state == MODULE_INSERTED) + return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; + return 0; } -- cgit v1.2.3-70-g09d2 From 2133ffbf08e7fca0614ea73cb5c43cc6435b4414 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:12:16 -0300 Subject: V4L/DVB (13745): [Mantis CA] Add some debug statements Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 34 ++++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_hif.c | 4 ++++ 2 files changed, 38 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index cd6bed73729..a8b8c88238e 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -25,6 +25,9 @@ static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr) { struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot); if (slot != 0) return -EINVAL; @@ -35,6 +38,9 @@ static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data) { struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot); if (slot != 0) return -EINVAL; @@ -45,6 +51,9 @@ static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, in static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr) { struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot); if (slot != 0) return -EINVAL; @@ -55,6 +64,9 @@ static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 a static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data) { struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot); if (slot != 0) return -EINVAL; @@ -64,22 +76,40 @@ static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) { + struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot); + return 0; } static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) { + struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot); + return 0; } static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) { + struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); + return 0; } static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open) { struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot); if (ca->slot_state == MODULE_INSERTED) return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; @@ -93,6 +123,7 @@ int mantis_ca_init(struct mantis_pci *mantis) struct mantis_ca *ca; int ca_flags = 0, result; + dprintk(verbose, MANTIS_DEBUG, 1, "Initializing Mantis CA"); if (!(ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL))) { dprintk(verbose, MANTIS_ERROR, 1, "Out of memory!, exiting .."); result = -ENOMEM; @@ -130,6 +161,9 @@ err: void mantis_ca_exit(struct mantis_pci *mantis) { struct mantis_ca *ca = mantis->mantis_ca; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis CA exit"); mantis_evmgr_exit(ca); dprintk(verbose, MANTIS_ERROR, 1, "Unregistering EN50221 device"); diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 6a1ea96c16d..42e0360e96d 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -61,6 +61,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0, data, count = 4; + dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num); hif_addr |= MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; @@ -91,6 +92,7 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0; + dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num); hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; @@ -116,6 +118,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) struct mantis_pci *mantis = ca->ca_priv; u32 data, hif_addr = 0; + dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr |= MANTIS_GPIF_HIFRDWRN; hif_addr |= MANTIS_GPIF_PCMCIAIOM; @@ -143,6 +146,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0; + dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr |= MANTIS_GPIF_PCMCIAIOM; -- cgit v1.2.3-70-g09d2 From fbe1e43abc6ada6bcd3e9866b01e41f093f12c62 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:12:51 -0300 Subject: V4L/DVB (13746): [Mantis CA] Bug: Remove duplicated symbol Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index a8b8c88238e..f6d70cb3f6f 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -161,7 +161,6 @@ err: void mantis_ca_exit(struct mantis_pci *mantis) { struct mantis_ca *ca = mantis->mantis_ca; - struct mantis_pci *mantis = ca->ca_priv; dprintk(verbose, MANTIS_DEBUG, 1, "Mantis CA exit"); -- cgit v1.2.3-70-g09d2 From a0c59063a7fe92524ab8fa6e31997b177a8f3029 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Fri, 4 Dec 2009 05:13:21 -0300 Subject: V4L/DVB (13747): [Mantis] Bug Fix!: Use Register Address rather than register field Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dma.c | 4 ++-- drivers/media/dvb/mantis/mantis_hif.c | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index 250f49a913a..d15a1eb980c 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -190,7 +190,7 @@ void mantis_dma_start(struct mantis_pci *mantis) mantis_risc_program(mantis); mmwrite(mantis->risc_dma, MANTIS_RISC_START); - mmwrite(mmread(MANTIS_GPIF_HIFADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_HIFADDR); + mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); mmwrite(0, MANTIS_DMA_CTL); mantis->last_block = mantis->finished_block = 0; @@ -210,7 +210,7 @@ void mantis_dma_stop(struct mantis_pci *mantis) mask = mmread(MANTIS_INT_MASK); dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); - mmwrite((mmread(MANTIS_GPIF_HIFADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_HIFADDR); + mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR); mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | MANTIS_DCAP_EN | diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 42e0360e96d..9e058be8726 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -72,7 +72,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) udelay(20); - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); if (mantis_hif_data_available(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer burst read failed", mantis->num); return -EREMOTEIO; @@ -81,7 +81,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - data = mmread(MANTIS_GPIF_HIFDIN); + data = mmread(MANTIS_GPIF_DIN); return (data >> 24) & 0xff; } @@ -100,8 +100,8 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */ - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); - mmwrite(data, MANTIS_GPIF_HIFDOUT); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); + mmwrite(data, MANTIS_GPIF_DOUT); ca->hif_job_queue = MANTIS_HIF_MEMWR; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { @@ -124,7 +124,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); ca->hif_job_queue = MANTIS_HIF_IOMRD; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { @@ -134,9 +134,9 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) } udelay(50); ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; - data = mmread(MANTIS_GPIF_HIFDIN); + data = mmread(MANTIS_GPIF_DIN); hif_addr |= MANTIS_GPIF_PCMCIAREG; - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); return data; } @@ -152,8 +152,8 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); - mmwrite(data, MANTIS_GPIF_HIFDOUT); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); + mmwrite(data, MANTIS_GPIF_DOUT); ca->hif_job_queue = MANTIS_HIF_IOMWR; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { @@ -164,7 +164,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) udelay(50); ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; hif_addr |= MANTIS_GPIF_PCMCIAREG; - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); return 0; } -- cgit v1.2.3-70-g09d2 From ea30d81a9634cb4c13bbef46877f0d7730c57552 Mon Sep 17 00:00:00 2001 From: Magnus Horlin Date: Fri, 4 Dec 2009 05:14:34 -0300 Subject: V4L/DVB (13748): [Mantis/VP-2040] Add support for VP-2040 (TDA10023 frontend based) Signed-off-by: Magnus Horlin Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 1 + drivers/media/dvb/mantis/mantis_dvb.c | 1 + drivers/media/dvb/mantis/mantis_vp2040.h | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index a164bb14363..b94d0515de4 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -119,6 +119,7 @@ static void mantis_load_config(struct mantis_pci *mantis) case MANTIS_VP_2033_DVB_C: // VP-2033 mantis->hwconfig = &vp2033_mantis_config; break; + case MANTIS_VP_2040_DVB_C: // VP-2040 case TERRATEC_CINERGY_C_PCI: // VP-2040 clone mantis->hwconfig = &vp2040_mantis_config; break; diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index ade444963c8..3940aed8af8 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -273,6 +273,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; + case MANTIS_VP_2040_DVB_C: // VP-2040 case TERRATEC_CINERGY_C_PCI: dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); mantis->fe = tda10023_attach(&tda10023_cu1216_config, &mantis->adapter, read_pwm(mantis)); diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h index 825ccbb87ad..69463cc4ccc 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.h +++ b/drivers/media/dvb/mantis/mantis_vp2040.h @@ -25,6 +25,7 @@ #include "mantis_common.h" #include "tda1002x.h" +#define MANTIS_VP_2040_DVB_C 0x0043 #define TERRATEC_CINERGY_C_PCI 0x1178 extern struct tda1002x_config tda10023_cu1216_config; -- cgit v1.2.3-70-g09d2 From ac23f4c86c3c901f95d72fc2262b22e6230d4feb Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:15:10 -0300 Subject: V4L/DVB (13749): [Mantis CA] CA_SLAVE: Do not change Slave Configuration setup (Need to sanitize this cleanly for different Slaves) Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 9e058be8726..d18fe415244 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -171,9 +171,11 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) int mantis_hif_init(struct mantis_ca *ca) { + struct mantis_slot *slot = ca->slot; struct mantis_pci *mantis = ca->ca_priv; u32 irqcfg; + slot[0].slave_cfg = 0x70773028; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); init_waitqueue_head(&ca->hif_data_wq); init_waitqueue_head(&ca->hif_opdone_wq); -- cgit v1.2.3-70-g09d2 From 4d5a28efda3ce12529e4b90832184f62c7a50848 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:15:38 -0300 Subject: V4L/DVB (13750): [Mantis] GPIO_CONTROL: Cache a given GPIO Bit Setup for a given event Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 +- drivers/media/dvb/mantis/mantis_core.c | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 0aa4001dea9..75f07736e00 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -137,7 +137,7 @@ struct mantis_pci { u32 sub_device_id; /* A12 A13 A14 */ - int gpio_status; + u32 gpio_status; struct mantis_ca *mantis_ca; }; diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index b94d0515de4..3fd3b0801cf 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -185,16 +185,15 @@ int mantis_core_exit(struct mantis_pci *mantis) // Turn the given bit on or off. void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) { - u32 currVal, newVal; - - currVal = mmread(MANTIS_GPIF_ADDR); + u32 cur; + cur = mmread(MANTIS_GPIF_ADDR); if (value) - newVal = currVal | (1 << bitpos); + mantis->gpio_status = cur | (1 << bitpos); else - newVal = currVal & (~(1 << bitpos)); + mantis->gpio_status = cur & (~(1 << bitpos)); - mmwrite(newVal, MANTIS_GPIF_ADDR); + mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR); mmwrite(0x00, MANTIS_GPIF_DOUT); udelay(100); } -- cgit v1.2.3-70-g09d2 From b2d8f5eafd31cd7bc722dc93057d8c5fd5b688ab Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:16:24 -0300 Subject: V4L/DVB (13751): [Mantis] GPIO_CONTROL: Do not toggle GPIO CW's on HIF operations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 ++ drivers/media/dvb/mantis/mantis_hif.c | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 75f07736e00..49f2f118b49 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -142,6 +142,8 @@ struct mantis_pci { struct mantis_ca *mantis_ca; }; +#define MANTIS_HIF_STATUS (mantis->gpio_status << 12) + extern unsigned int verbose; extern unsigned int devs; extern unsigned int i2c; diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index d18fe415244..96611b67cb4 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -56,6 +56,7 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) return rc; } + int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) { struct mantis_pci *mantis = ca->ca_priv; @@ -67,7 +68,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; - mmwrite(hif_addr, MANTIS_GPIF_BRADDR); + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_BRADDR); mmwrite(count, MANTIS_GPIF_BRBYTES); udelay(20); @@ -100,7 +101,7 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */ - mmwrite(hif_addr, MANTIS_GPIF_ADDR); + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); ca->hif_job_queue = MANTIS_HIF_MEMWR; @@ -124,7 +125,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; - mmwrite(hif_addr, MANTIS_GPIF_ADDR); + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); ca->hif_job_queue = MANTIS_HIF_IOMRD; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { @@ -152,7 +153,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; - mmwrite(hif_addr, MANTIS_GPIF_ADDR); + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); ca->hif_job_queue = MANTIS_HIF_IOMWR; -- cgit v1.2.3-70-g09d2 From b619f9f8a111be3f6ec8ec2671eb93c66a673b90 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:17:14 -0300 Subject: V4L/DVB (13752): [Mantis CA] CAM_CONTROL: All CAM control operations now handled by the worker thread Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 6eecd54a445..4873fa9586e 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -183,20 +183,7 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, mantis->subsystem_device = pdev->subsystem_device; init_waitqueue_head(&mantis->i2c_wq); - // CAM bypass - //mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ1, MANTIS_INT_MASK); - dprintk(verbose, MANTIS_INFO, 0, "\ngpif status: %04x irqcfg: %04x\n", mmread(0x9c), mmread(0x98)); - if ((mmread(0x9c) & 0x200) != 0) { //CAM inserted - msleep_interruptible(1); - if ((mmread(0x9c) & 0x200) != 0) - mmwrite(((mmread(0x98) | 0x01) & ~0x02), 0x98); - else - mmwrite(((mmread(0x98) | 0x02) & ~0x01), 0x98); - - } else { - mmwrite(((mmread(0x98) | 0x02) & ~0x01), 0x98); - } - mantis_set_direction(mantis, 0); + mantis_set_direction(mantis, 0); /* CAM bypass */ if (!latency) pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 32); -- cgit v1.2.3-70-g09d2 From fb6de9c5fe13fd5cd866c49204e6bd91d73f83b0 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:17:46 -0300 Subject: V4L/DVB (13753): [Mantis CA] SLOT_CONTROL: Implement Slot RESET Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index f6d70cb3f6f..a30eb844ffd 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -80,6 +80,11 @@ static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) struct mantis_pci *mantis = ca->ca_priv; dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot); + udelay(500); /* Wait.. */ + mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */ + udelay(500); + mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */ + msleep(1000); return 0; } -- cgit v1.2.3-70-g09d2 From 990f8d1e161429ee1a0e9708f7989543e4648f73 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:18:27 -0300 Subject: V4L/DVB (13754): [Mantis] CAM_CONTROL: Implement TS control Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 1 + drivers/media/dvb/mantis/mantis_common.h | 2 ++ drivers/media/dvb/mantis/mantis_core.h | 4 ---- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index a30eb844ffd..b9d808bf710 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -105,6 +105,7 @@ static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) struct mantis_pci *mantis = ca->ca_priv; dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); + mantis_set_direction(mantis, 1); /* Enable TS through CAM */ return 0; } diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 49f2f118b49..ac3eefec0a7 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -153,6 +153,8 @@ extern int mantis_dvb_exit(struct mantis_pci *mantis); extern void mantis_dma_xfer(unsigned long data); extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); +extern void mantis_set_direction(struct mantis_pci *mantis, int direction); + extern int mantis_ca_init(struct mantis_pci *mantis); extern void mantis_ca_exit(struct mantis_pci *mantis); diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/dvb/mantis/mantis_core.h index 31b2a756d99..a8093940993 100644 --- a/drivers/media/dvb/mantis/mantis_core.h +++ b/drivers/media/dvb/mantis/mantis_core.h @@ -53,9 +53,5 @@ extern int mantis_i2c_init(struct mantis_pci *mantis); extern int mantis_i2c_exit(struct mantis_pci *mantis); extern int mantis_core_init(struct mantis_pci *mantis); extern int mantis_core_exit(struct mantis_pci *mantis); -//extern void mantis_fe_powerup(struct mantis_pci *mantis); -//extern void mantis_fe_powerdown(struct mantis_pci *mantis); -//extern void mantis_fe_reset(struct dvb_frontend *fe); -extern void mantis_set_direction(struct mantis_pci *mantis, int direction); #endif //__MANTIS_CORE_H -- cgit v1.2.3-70-g09d2 From f9ce1c3f32aa472c667c4d43d01c42922fb356ca Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:18:53 -0300 Subject: V4L/DVB (13755): [Mantis CA] CAM_CONTROL: Use appropriate flags Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index b9d808bf710..2c49f6bae49 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -138,6 +138,9 @@ int mantis_ca_init(struct mantis_pci *mantis) ca->ca_priv = mantis; mantis->mantis_ca = ca; + ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | + DVB_CA_EN50221_FLAG_IRQ_FR | + DVB_CA_EN50221_FLAG_IRQ_DA; /* register CA interface */ ca->en50221.owner = THIS_MODULE; -- cgit v1.2.3-70-g09d2 From 05691cdbf479282e3d3c2e3386cb865cbf611e3a Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:19:26 -0300 Subject: V4L/DVB (13756): [Mantis CA] CAM_CONTROL: Use CAMCHANGE_IRQ events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index dbcdca3a8f0..79c3c625e2e 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -39,12 +39,18 @@ static void mantis_hifevm_work(struct work_struct *work) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); mantis_event_cam_plugin(ca); + dvb_ca_en50221_camchange_irq(&ca->en50221, + 0, + DVB_CA_EN50221_CAMCHANGE_INSERTED); } } else { if (gpif_stat & MANTIS_CARD_PLUGOUT) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); mantis_event_cam_unplug(ca); + dvb_ca_en50221_camchange_irq(&ca->en50221, + 0, + DVB_CA_EN50221_CAMCHANGE_REMOVED); } } -- cgit v1.2.3-70-g09d2 From bb928a7a21273f67455912f0935ff943ddb35d0c Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:20:14 -0300 Subject: V4L/DVB (13757): [Mantis CA] CAM_CONTROL: Use FRDA_IRQ Events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 79c3c625e2e..ee049555a3c 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -69,8 +69,7 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_GPIF_BRRDY) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; - if (ca->hif_job_queue & MANTIS_HIF_MEMRD) - wake_up(&ca->hif_brrdyw_wq); + dvb_ca_en50221_frda_irq(&ca->en50221, 0); } if (gpif_stat & MANTIS_GPIF_WRACK) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); -- cgit v1.2.3-70-g09d2 From 2ec9b00bd0386b71c8a84a3990a13ea9656fe8dd Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:20:44 -0300 Subject: V4L/DVB (13758): [Mantis CA] CAM_CONTROL: Use CAMREADY_IRQ event Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 1 + drivers/media/dvb/mantis/mantis_evm.c | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 2c49f6bae49..abd8855cabf 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -85,6 +85,7 @@ static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) udelay(500); mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */ msleep(1000); + dvb_ca_en50221_camready_irq(&ca->en50221, 0); return 0; } diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index ee049555a3c..469571508d1 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -82,10 +82,7 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_SBUF_OPDONE) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); - if (ca->hif_job_queue) { - wake_up(&ca->hif_opdone_wq); - ca->hif_event = MANTIS_SBUF_OPDONE; - } + } } -- cgit v1.2.3-70-g09d2 From 9c8679554db8cf39ccec5a90cfaa12b164585556 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:21:05 -0300 Subject: V4L/DVB (13759): [Mantis] HIF I/O: Use the LSB octet only Thanks to Abylai Ospan for pointing this out. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 96611b67cb4..1ccd8696953 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -139,7 +139,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_ADDR); - return data; + return (u8) data; } int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) -- cgit v1.2.3-70-g09d2 From 86c75c5c2b9318f4b3218615ada18badabd3f166 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Fri, 4 Dec 2009 05:21:27 -0300 Subject: V4L/DVB (13760): [Mantis CA] CA_MODULE: Look for module status on driver load Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pcmcia.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 47cc720d35d..59f1a06f0d9 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -83,6 +83,9 @@ int mantis_pcmcia_init(struct mantis_ca *ca) dprintk(verbose, MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_INSERTED; + dvb_ca_en50221_camchange_irq(&ca->en50221, + 0, + DVB_CA_EN50221_CAMCHANGE_INSERTED); } else { dprintk(verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG); -- cgit v1.2.3-70-g09d2 From cc0e4aacaf4c3660fa759ce1299377baaf9efd8b Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:21:51 -0300 Subject: V4L/DVB (13761): [Mantis] HIF I/O: Temporary workaround, use SBUF_OPDONE flag instead Dnumgis got hit with this bug, using a temporary workaround for the time being rather than digging deep at this point. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 469571508d1..532bcfff5ae 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -68,8 +68,6 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_GPIF_BRRDY) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); - ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; - dvb_ca_en50221_frda_irq(&ca->en50221, 0); } if (gpif_stat & MANTIS_GPIF_WRACK) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); @@ -82,7 +80,8 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_SBUF_OPDONE) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); - + ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; + dvb_ca_en50221_frda_irq(&ca->en50221, 0); } } -- cgit v1.2.3-70-g09d2 From 88a6fa9dfec0a585409acbb49a7f86a933b35d2b Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:22:33 -0300 Subject: V4L/DVB (13762): [Mantis CA] CA_MODULE: Look for the module status on driver unload as well Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pcmcia.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 59f1a06f0d9..4156a082088 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -90,6 +90,9 @@ int mantis_pcmcia_init(struct mantis_ca *ca) dprintk(verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_XTRACTED; + dvb_ca_en50221_camchange_irq(&ca->en50221, + 0, + DVB_CA_EN50221_CAMCHANGE_REMOVED); } return 0; -- cgit v1.2.3-70-g09d2 From 8e0d58ecee2abc12f298862b7f9a90d1593e8006 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:22:57 -0300 Subject: V4L/DVB (13763): [Mantis] HIF I/O: trim delays a bit appropriately Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 1ccd8696953..880b99634c2 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -133,11 +133,11 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - udelay(50); ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; data = mmread(MANTIS_GPIF_DIN); hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_ADDR); + udelay(50); return (u8) data; } @@ -162,10 +162,10 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - udelay(50); ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_ADDR); + udelay(50); return 0; } -- cgit v1.2.3-70-g09d2 From 5e2a0c99019bbc78d6fb00caf7a79f03df020b3c Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:23:17 -0300 Subject: V4L/DVB (13764): [Mantis CA] SLOT: Add some debug status Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index abd8855cabf..b79a89276e3 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -118,8 +118,12 @@ static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot); - if (ca->slot_state == MODULE_INSERTED) + if (ca->slot_state == MODULE_INSERTED) { + dprintk(verbose, MANTIS_DEBUG, 1, "CA Module present and ready"); return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; + } else { + dprintk(verbose, MANTIS_DEBUG, 1, "CA Module not present or not ready"); + } return 0; } -- cgit v1.2.3-70-g09d2 From 8b9c385f765bcc7fc5ae802830ffcb4b6ca6bc9c Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:23:38 -0300 Subject: V4L/DVB (13765): [Mantis] HIF I/O: Add some debug statements Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 880b99634c2..c2cecc3d7b1 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -51,6 +51,7 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num); rc = -EREMOTEIO; } + dprintk(verbose, MANTIS_DEBUG, 1, "Smart Buffer Operation complete"); ca->hif_event &= ~MANTIS_SBUF_OPDONE; udelay(5); return rc; @@ -83,7 +84,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) return -EREMOTEIO; } data = mmread(MANTIS_GPIF_DIN); - + dprintk(verbose, MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data); return (data >> 24) & 0xff; } @@ -111,6 +112,8 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) return -EREMOTEIO; } ca->hif_job_queue &= ~MANTIS_HIF_MEMWR; + dprintk(verbose, MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr); + return 0; } @@ -137,6 +140,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) data = mmread(MANTIS_GPIF_DIN); hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_ADDR); + dprintk(verbose, MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); udelay(50); return (u8) data; @@ -165,6 +169,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_ADDR); + dprintk(verbose, MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); udelay(50); return 0; -- cgit v1.2.3-70-g09d2 From b29453aca0eeecba52a76c3d67b1a52c3ca6e656 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Fri, 4 Dec 2009 05:24:01 -0300 Subject: V4L/DVB (13766): [Mantis] Bug: Fix wrong exit condition Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 532bcfff5ae..214ae5ee31e 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -31,8 +31,6 @@ static void mantis_hifevm_work(struct work_struct *work) gpif_stat = mmread(MANTIS_GPIF_STATUS); gpif_mask = mmread(MANTIS_GPIF_IRQCFG); - if (!((gpif_stat & 0xff) & (gpif_mask & 0xff))) - return; if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { -- cgit v1.2.3-70-g09d2 From 18b6de42d77e7762be929a4a858c359de352e1e2 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:24:47 -0300 Subject: V4L/DVB (13767): [Mantis/VP-1041] Bug: Add in missing Master clock settings Thanks to Ershov and Igor for pointing it out. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_vp1041.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 7dee1af0d64..8eb1afdab11 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -267,6 +267,9 @@ struct stb0899_config vp1041_config = { .xtal_freq = 27000000, .inversion = IQ_SWAP_ON, /* 1 */ + .lo_clk = 76500000, + .hi_clk = 99000000, + .esno_ave = STB0899_DVBS2_ESNO_AVE, .esno_quant = STB0899_DVBS2_ESNO_QUANT, .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE, -- cgit v1.2.3-70-g09d2 From adcc9dd57e814d5ac3928f92f431fbe4808e936f Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:25:18 -0300 Subject: V4L/DVB (13768): [Mantis] Enable WRACK Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 10 +++++++++- drivers/media/dvb/mantis/mantis_hif.c | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 214ae5ee31e..000cf396a2c 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -27,11 +27,19 @@ static void mantis_hifevm_work(struct work_struct *work) struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work); struct mantis_pci *mantis = ca->ca_priv; - u32 gpif_stat, gpif_mask; + u32 gpif_stat, gpif_mask, rst_mask, rst_stat; + + rst_mask = MANTIS_GPIF_WRACK | + MANTIS_GPIF_OTHERR | + MANTIS_SBUF_WSTO | + MANTIS_GPIF_EXTIRQ; gpif_stat = mmread(MANTIS_GPIF_STATUS); gpif_mask = mmread(MANTIS_GPIF_IRQCFG); + rst_stat = gpif_stat & rst_mask; + mmwrite(rst_stat, MANTIS_GPIF_STATUS); + if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index c2cecc3d7b1..2f1a6cb943d 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -188,6 +188,7 @@ int mantis_hif_init(struct mantis_ca *ca) irqcfg = mmread(MANTIS_GPIF_IRQCFG); irqcfg |= MANTIS_MASK_BRRDY; + irqcfg |= MANTIS_MASK_WRACK; mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); return 0; -- cgit v1.2.3-70-g09d2 From 9e49e8d913209e7221f761193f18a91d130b9e2d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:25:45 -0300 Subject: V4L/DVB (13769): [Mantis] Smart Buffer Burst Read Ready cannot flag FR/DA Irq Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 000cf396a2c..1594bb85a20 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -72,9 +72,9 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_SBUF_OVFLW) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); - if (gpif_stat & MANTIS_GPIF_BRRDY) { + if (gpif_stat & MANTIS_GPIF_BRRDY) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); - } + if (gpif_stat & MANTIS_GPIF_WRACK) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); -- cgit v1.2.3-70-g09d2 From f668c7292bda7f64400eaa8d45c3a785eecab990 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:26:18 -0300 Subject: V4L/DVB (13770): [Mantis] Bug Do not trigger FR/DA IRQ from SBUF OPDONE Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 1594bb85a20..d603601c09b 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -87,7 +87,6 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_SBUF_OPDONE) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; - dvb_ca_en50221_frda_irq(&ca->en50221, 0); } } -- cgit v1.2.3-70-g09d2 From 17b77fc2d404910ca691661038ceb4c02d912d16 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:26:46 -0300 Subject: V4L/DVB (13771): [Mantis] Reset Flags at the earliest possible Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 ++ drivers/media/dvb/mantis/mantis_evm.c | 18 +++++------------- drivers/media/dvb/mantis/mantis_pci.c | 12 ++++++++++++ 3 files changed, 19 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index ac3eefec0a7..27ecfdb6e6f 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -139,6 +139,8 @@ struct mantis_pci { /* A12 A13 A14 */ u32 gpio_status; + u32 gpif_status; + struct mantis_ca *mantis_ca; }; diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index d603601c09b..4c4c1448ddd 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -27,19 +27,11 @@ static void mantis_hifevm_work(struct work_struct *work) struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work); struct mantis_pci *mantis = ca->ca_priv; - u32 gpif_stat, gpif_mask, rst_mask, rst_stat; - - rst_mask = MANTIS_GPIF_WRACK | - MANTIS_GPIF_OTHERR | - MANTIS_SBUF_WSTO | - MANTIS_GPIF_EXTIRQ; + u32 gpif_stat, gpif_mask; gpif_stat = mmread(MANTIS_GPIF_STATUS); gpif_mask = mmread(MANTIS_GPIF_IRQCFG); - rst_stat = gpif_stat & rst_mask; - mmwrite(rst_stat, MANTIS_GPIF_STATUS); - if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); @@ -60,13 +52,13 @@ static void mantis_hifevm_work(struct work_struct *work) } } - if (gpif_stat & MANTIS_GPIF_EXTIRQ) + if (mantis->gpif_status & MANTIS_GPIF_EXTIRQ) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); - if (gpif_stat & MANTIS_SBUF_WSTO) + if (mantis->gpif_status & MANTIS_SBUF_WSTO) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); - if (gpif_stat & MANTIS_GPIF_OTHERR) + if (mantis->gpif_status & MANTIS_GPIF_OTHERR) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); if (gpif_stat & MANTIS_SBUF_OVFLW) @@ -75,7 +67,7 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_GPIF_BRRDY) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); - if (gpif_stat & MANTIS_GPIF_WRACK) + if (mantis->gpif_status & MANTIS_GPIF_WRACK) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); if (gpif_stat & MANTIS_GPIF_INTSTAT) diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 4873fa9586e..f57e2a43b9e 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -53,6 +53,8 @@ MODULE_DEVICE_TABLE(pci, mantis_pci_table); static irqreturn_t mantis_pci_irq(int irq, void *dev_id) { u32 stat = 0, mask = 0, lstat = 0, mstat = 0; + u32 rst_stat = 0, rst_mask = 0; + struct mantis_pci *mantis; struct mantis_ca *ca; @@ -69,6 +71,15 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) if (!(stat & mask)) return IRQ_NONE; + rst_mask = MANTIS_GPIF_WRACK | + MANTIS_GPIF_OTHERR | + MANTIS_SBUF_WSTO | + MANTIS_GPIF_EXTIRQ; + + rst_stat = mmread(MANTIS_GPIF_STATUS); + rst_stat &= rst_mask; + mmwrite(rst_stat, MANTIS_GPIF_STATUS); + mantis->mantis_int_stat = stat; mantis->mantis_int_mask = mask; dprintk(verbose, MANTIS_DEBUG, 0, "=== Interrupts[%04x/%04x]= [", stat, mask); @@ -77,6 +88,7 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) } if (stat & MANTIS_INT_IRQ0) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); + mantis->gpif_status = rst_stat; schedule_work(&ca->hif_evm_work); } if (stat & MANTIS_INT_IRQ1) { -- cgit v1.2.3-70-g09d2 From 578413228ae72a09b29bf29e879e5b919ded0ac4 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:27:26 -0300 Subject: V4L/DVB (13772): [Mantis] Do not enable Common Memory Access Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 2f1a6cb943d..151de2d687e 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -138,8 +138,6 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) } ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; data = mmread(MANTIS_GPIF_DIN); - hif_addr |= MANTIS_GPIF_PCMCIAREG; - mmwrite(hif_addr, MANTIS_GPIF_ADDR); dprintk(verbose, MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); udelay(50); @@ -167,8 +165,6 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) return -EREMOTEIO; } ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; - hif_addr |= MANTIS_GPIF_PCMCIAREG; - mmwrite(hif_addr, MANTIS_GPIF_ADDR); dprintk(verbose, MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); udelay(50); -- cgit v1.2.3-70-g09d2 From c90d345fd7d66899d743611a47163f9904df90bc Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:27:53 -0300 Subject: V4L/DVB (13773): [Mantis] Enable all interrupts Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 151de2d687e..fa4bb6dc324 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -182,9 +182,14 @@ int mantis_hif_init(struct mantis_ca *ca) init_waitqueue_head(&ca->hif_data_wq); init_waitqueue_head(&ca->hif_opdone_wq); - irqcfg = mmread(MANTIS_GPIF_IRQCFG); - irqcfg |= MANTIS_MASK_BRRDY; - irqcfg |= MANTIS_MASK_WRACK; + irqcfg = mmread(MANTIS_GPIF_IRQCFG); + irqcfg = MANTIS_MASK_BRRDY | + MANTIS_MASK_WRACK | + MANTIS_MASK_EXTIRQ | + MANTIS_MASK_WSTO | + MANTIS_MASK_OTHERR | + MANTIS_MASK_OVFLW; + mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); return 0; -- cgit v1.2.3-70-g09d2 From c02e15150c85619f22a98675124503ed93bf1914 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Fri, 4 Dec 2009 05:28:24 -0300 Subject: V4L/DVB (13774): [Mantis] Remove redundant wait for Burst Reads, wakeup the HIF event Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 2 ++ drivers/media/dvb/mantis/mantis_hif.c | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 4c4c1448ddd..008e2c28c06 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -79,6 +79,8 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_SBUF_OPDONE) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; + ca->hif_event = MANTIS_SBUF_OPDONE; + wake_up(&ca->hif_opdone_wq); } } diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index fa4bb6dc324..6c51d178001 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -75,10 +75,6 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) udelay(20); mmwrite(hif_addr, MANTIS_GPIF_ADDR); - if (mantis_hif_data_available(ca) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer burst read failed", mantis->num); - return -EREMOTEIO; - } if (mantis_hif_sbuf_opdone_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; -- cgit v1.2.3-70-g09d2 From b9fd5877463605b91743552b4989666792bf4fbc Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:29:03 -0300 Subject: V4L/DVB (13775): [Mantis] Remove unnecessary job queues Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 10 ---------- drivers/media/dvb/mantis/mantis_link.h | 1 - 2 files changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 6c51d178001..621dce3eb5d 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -97,17 +97,13 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) hif_addr |= addr; mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */ - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); - ca->hif_job_queue = MANTIS_HIF_MEMWR; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { - ca->hif_job_queue &= ~MANTIS_HIF_MEMWR; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - ca->hif_job_queue &= ~MANTIS_HIF_MEMWR; dprintk(verbose, MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr); return 0; @@ -125,14 +121,11 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) hif_addr |= addr; mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); - ca->hif_job_queue = MANTIS_HIF_IOMRD; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { - ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; data = mmread(MANTIS_GPIF_DIN); dprintk(verbose, MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); udelay(50); @@ -154,13 +147,10 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); - ca->hif_job_queue = MANTIS_HIF_IOMWR; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { - ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; dprintk(verbose, MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); udelay(50); diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 23ff2d6aadb..a85f5021526 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -51,7 +51,6 @@ struct mantis_ca { wait_queue_head_t hif_opdone_wq; wait_queue_head_t hif_brrdyw_wq; wait_queue_head_t hif_data_wq; - u32 hif_job_queue; enum mantis_sbuf_status sbuf_status; -- cgit v1.2.3-70-g09d2 From ac8f04d2723b3de7c36430d67401ce89c858e117 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:29:25 -0300 Subject: V4L/DVB (13776): [Mantis] Use a simple timeout instead, interruptible timeouts sleep unnecessarily too long Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 621dce3eb5d..a2359f7e146 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -44,9 +44,9 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) struct mantis_pci *mantis = ca->ca_priv; int rc = 0; - if (wait_event_interruptible_timeout(ca->hif_opdone_wq, - ca->hif_event & MANTIS_SBUF_OPDONE, - msecs_to_jiffies(500)) == -ERESTARTSYS) { + if (wait_event_timeout(ca->hif_opdone_wq, + ca->hif_event & MANTIS_SBUF_OPDONE, + msecs_to_jiffies(500)) == -ERESTARTSYS) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num); rc = -EREMOTEIO; -- cgit v1.2.3-70-g09d2 From e0e099a708043a2341d8987014ce4ba98a4dbd30 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:29:48 -0300 Subject: V4L/DVB (13777): [Mantis] Use a Write wait queue for Write events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 34 ++++++++++++++++++++++++++++++++-- drivers/media/dvb/mantis/mantis_link.h | 1 + 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index a2359f7e146..dc50fac0d15 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -57,6 +57,35 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) return rc; } +static int mantis_hif_write_wait(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 opdone = 0, timeout = 0; + int rc = 0; + + if (wait_event_timeout(ca->hif_write_wq, + mantis->gpif_status & MANTIS_GPIF_WRACK, + msecs_to_jiffies(500)) == -ERESTARTSYS) { + + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed out !", mantis->num); + rc = -EREMOTEIO; + } + dprintk(verbose, MANTIS_DEBUG, 1, "Write Acknowledged"); + mantis->gpif_status &= ~MANTIS_GPIF_WRACK; + while (!opdone) { + opdone = (mmread(MANTIS_GPIF_STATUS) & MANTIS_SBUF_OPDONE); + udelay(500); + timeout++; + if (timeout > 100) { + dprintk(verbose, MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num); + rc = -ETIMEDOUT; + break; + } + } + dprintk(verbose, MANTIS_DEBUG, 1, "HIF Write success"); + return rc; +} + int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) { @@ -100,7 +129,7 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); - if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + if (mantis_hif_write_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } @@ -147,7 +176,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); - if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + if (mantis_hif_write_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } @@ -167,6 +196,7 @@ int mantis_hif_init(struct mantis_ca *ca) dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); init_waitqueue_head(&ca->hif_data_wq); init_waitqueue_head(&ca->hif_opdone_wq); + init_waitqueue_head(&ca->hif_write_wq); irqcfg = mmread(MANTIS_GPIF_IRQCFG); irqcfg = MANTIS_MASK_BRRDY | diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index a85f5021526..599ff1b57e4 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -51,6 +51,7 @@ struct mantis_ca { wait_queue_head_t hif_opdone_wq; wait_queue_head_t hif_brrdyw_wq; wait_queue_head_t hif_data_wq; + wait_queue_head_t hif_write_wq; /* HIF Write op */ enum mantis_sbuf_status sbuf_status; -- cgit v1.2.3-70-g09d2 From 4d019faf48ff03b6ff3463d8e5da54d61f153623 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:30:11 -0300 Subject: V4L/DVB (13778): [Mantis] Wr ACK is already handled in the fast path, do not use the event manager to handle the fast events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 008e2c28c06..9be55f7942d 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -67,9 +67,6 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_GPIF_BRRDY) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); - if (mantis->gpif_status & MANTIS_GPIF_WRACK) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); - if (gpif_stat & MANTIS_GPIF_INTSTAT) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); -- cgit v1.2.3-70-g09d2 From 25e9eba42ce11a05933068cf6a42dd8d4ed5edb8 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:30:33 -0300 Subject: V4L/DVB (13779): [Mantis] Missing wakeup for write queue Thanks to Sigmund for pointing it out Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index f57e2a43b9e..a068ffb3253 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -89,6 +89,7 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) if (stat & MANTIS_INT_IRQ0) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); mantis->gpif_status = rst_stat; + wake_up(&ca->hif_write_wq); schedule_work(&ca->hif_evm_work); } if (stat & MANTIS_INT_IRQ1) { -- cgit v1.2.3-70-g09d2 From c63e507346c042af7fe26d49bbbdce9898ea3eea Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Fri, 4 Dec 2009 05:30:59 -0300 Subject: V4L/DVB (13780): [Mantis] HIF I/O: Enable Interrupts for Read Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index dc50fac0d15..323d1fb0a55 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -149,6 +149,11 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_BRADDR); + mmwrite(1, MANTIS_GPIF_BRBYTES); + + udelay(20); + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); if (mantis_hif_sbuf_opdone_wait(ca) != 0) { -- cgit v1.2.3-70-g09d2 From b29f6ac248e49d8425aa91afb1b53d1f6d47ebe3 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:31:21 -0300 Subject: V4L/DVB (13781): [Mantis CA] Bug: Fix wrong usage of HIFRDWRN Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 323d1fb0a55..3368253aea6 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -53,7 +53,6 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) } dprintk(verbose, MANTIS_DEBUG, 1, "Smart Buffer Operation complete"); ca->hif_event &= ~MANTIS_SBUF_OPDONE; - udelay(5); return rc; } @@ -93,17 +92,16 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) u32 hif_addr = 0, data, count = 4; dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num); - hif_addr |= MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; + hif_addr |= MANTIS_HIF_STATUS; hif_addr |= addr; - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_BRADDR); + mmwrite(hif_addr, MANTIS_GPIF_BRADDR); mmwrite(count, MANTIS_GPIF_BRBYTES); - udelay(20); + mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); - mmwrite(hif_addr, MANTIS_GPIF_ADDR); if (mantis_hif_sbuf_opdone_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; @@ -123,10 +121,11 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; - hif_addr |= addr; + hif_addr |= MANTIS_HIF_STATUS; + hif_addr |= addr; mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */ - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); if (mantis_hif_write_wait(ca) != 0) { @@ -145,16 +144,14 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; - hif_addr |= MANTIS_GPIF_HIFRDWRN; hif_addr |= MANTIS_GPIF_PCMCIAIOM; + hif_addr |= MANTIS_HIF_STATUS; hif_addr |= addr; - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_BRADDR); + mmwrite(hif_addr, MANTIS_GPIF_BRADDR); mmwrite(1, MANTIS_GPIF_BRBYTES); - udelay(20); - - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); + mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); if (mantis_hif_sbuf_opdone_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); @@ -176,9 +173,10 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr |= MANTIS_GPIF_PCMCIAIOM; + hif_addr |= MANTIS_HIF_STATUS; hif_addr |= addr; - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); if (mantis_hif_write_wait(ca) != 0) { -- cgit v1.2.3-70-g09d2 From e26c2b46201e5ae38111391c293cec08870b7f6d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:31:45 -0300 Subject: V4L/DVB (13782): [Mantis] Temporarily disable FRDA irq Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index b79a89276e3..177b04813ff 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -143,10 +143,7 @@ int mantis_ca_init(struct mantis_pci *mantis) ca->ca_priv = mantis; mantis->mantis_ca = ca; - ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | - DVB_CA_EN50221_FLAG_IRQ_FR | - DVB_CA_EN50221_FLAG_IRQ_DA; - + ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; /* register CA interface */ ca->en50221.owner = THIS_MODULE; ca->en50221.read_attribute_mem = mantis_ca_read_attr_mem; -- cgit v1.2.3-70-g09d2 From f5701b67767c6b81a035c9e2b539025f91d1e84d Mon Sep 17 00:00:00 2001 From: Marko Viitamaki Date: Fri, 4 Dec 2009 05:32:30 -0300 Subject: V4L/DVB (13783): [Mantis/Technisat Cablestar HD2] Add support for the Technisat Cablestar HD2 Signed-off-by: Marko Viitamaki Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 1 + drivers/media/dvb/mantis/mantis_dvb.c | 1 + drivers/media/dvb/mantis/mantis_vp2040.h | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 3fd3b0801cf..c3d0d53bc38 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -121,6 +121,7 @@ static void mantis_load_config(struct mantis_pci *mantis) break; case MANTIS_VP_2040_DVB_C: // VP-2040 case TERRATEC_CINERGY_C_PCI: // VP-2040 clone + case TECHNISAT_CABLESTAR_HD2: mantis->hwconfig = &vp2040_mantis_config; break; case MANTIS_VP_3030_DVB_T: // VP-3030 diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 3940aed8af8..c3a35bee468 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -275,6 +275,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) break; case MANTIS_VP_2040_DVB_C: // VP-2040 case TERRATEC_CINERGY_C_PCI: + case TECHNISAT_CABLESTAR_HD2: dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); mantis->fe = tda10023_attach(&tda10023_cu1216_config, &mantis->adapter, read_pwm(mantis)); if (mantis->fe) { diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h index 69463cc4ccc..645dade7543 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.h +++ b/drivers/media/dvb/mantis/mantis_vp2040.h @@ -27,6 +27,7 @@ #define MANTIS_VP_2040_DVB_C 0x0043 #define TERRATEC_CINERGY_C_PCI 0x1178 +#define TECHNISAT_CABLESTAR_HD2 0x0002 extern struct tda1002x_config tda10023_cu1216_config; extern struct mantis_hwconfig vp2040_mantis_config; -- cgit v1.2.3-70-g09d2 From ff63ac56705539e162d2f020a0c2a607eae37d7b Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:32:51 -0300 Subject: V4L/DVB (13784): [Mantis] Use PCI API instead of hardcoded length Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index a068ffb3253..d3a62b18590 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -169,7 +169,10 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, goto err0; } - if ((mantis->mantis_mmio = ioremap(mantis->mantis_addr, 0x1000)) == NULL) { + mantis->mantis_mmio = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + + if (!mantis->mantis_mmio) { dprintk(verbose, MANTIS_ERROR, 1, "IO remap failed"); ret = -ENODEV; goto err1; -- cgit v1.2.3-70-g09d2 From 13d5036ea0636e6204e1b17bd12ea25061a686be Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:33:10 -0300 Subject: V4L/DVB (13785): [Mantis] Do not disable IRQ's while being invoked Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index d3a62b18590..94abcee3fc7 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -181,8 +181,11 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, // Clear and disable all interrupts at startup // to avoid lockup situations mmwrite(0x00, MANTIS_INT_MASK); - if (request_irq(pdev->irq, mantis_pci_irq, IRQF_SHARED | IRQF_DISABLED, - DRIVER_NAME, mantis) < 0) { + if (request_irq(pdev->irq, + mantis_pci_irq, + IRQF_SHARED, + DRIVER_NAME, + mantis) < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis IRQ reg failed"); ret = -ENODEV; -- cgit v1.2.3-70-g09d2 From 263645de70175d8b5a5e392a1856e99e2e1b7209 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:33:31 -0300 Subject: V4L/DVB (13786): [Mantis] Bug: HIF bits already shifted .. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 27ecfdb6e6f..6b9f92b4ab3 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -144,7 +144,7 @@ struct mantis_pci { struct mantis_ca *mantis_ca; }; -#define MANTIS_HIF_STATUS (mantis->gpio_status << 12) +#define MANTIS_HIF_STATUS (mantis->gpio_status) extern unsigned int verbose; extern unsigned int devs; -- cgit v1.2.3-70-g09d2 From 616f75e1979f5bd1f3241581c720349c2c31f6e7 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:33:56 -0300 Subject: V4L/DVB (13787): [Mantis] Fix build Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 5 ++++- drivers/media/dvb/mantis/mantis_vp1033.c | 2 +- drivers/media/dvb/mantis/mantis_vp2040.c | 2 +- drivers/media/dvb/mantis/mantis_vp2040.h | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index c3a35bee468..5172e856354 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -32,6 +32,8 @@ #include "mantis_vp2040.h" #include "mantis_vp3030.h" +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* Tuner power supply control */ void mantis_fe_powerup(struct mantis_pci *mantis) { @@ -128,7 +130,8 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) dprintk(verbose, MANTIS_DEBUG, 1, "dvb_register_adapter"); if (dvb_register_adapter(&mantis->dvb_adapter, "Mantis dvb adapter", THIS_MODULE, - &mantis->pdev->dev) < 0) { + &mantis->pdev->dev, + adapter_nr) < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Error registering adapter"); return -ENODEV; diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index daf02c12d29..797c4e0c7ea 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -74,7 +74,7 @@ struct stv0299_config lgtdqcs001f_config = { .invert = 1, // .enhanced_tuning = 0, .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_0, +// .lock_output = STV0229_LOCKOUTPUT_0, .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = lgtdqcs001f_set_symbol_rate, diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index 07da73827fd..f77be7b6491 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -30,7 +30,7 @@ struct mantis_hwconfig vp2040_mantis_config = { .ts_size = MANTIS_TS_204, }; -struct tda1002x_config tda10023_cu1216_config = { +struct tda10023_config tda10023_cu1216_config = { .demod_address = 0x18 >> 1, .invert = 1, }; diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h index 645dade7543..c7457543d8b 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.h +++ b/drivers/media/dvb/mantis/mantis_vp2040.h @@ -29,7 +29,7 @@ #define TERRATEC_CINERGY_C_PCI 0x1178 #define TECHNISAT_CABLESTAR_HD2 0x0002 -extern struct tda1002x_config tda10023_cu1216_config; +extern struct tda10023_config tda10023_cu1216_config; extern struct mantis_hwconfig vp2040_mantis_config; #endif //__MANTIS_VP2040_H -- cgit v1.2.3-70-g09d2 From f684336bba673b6656cb98144130ab52dafc3240 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:34:19 -0300 Subject: V4L/DVB (13788): [Mantis CA] use a lock for the relevant CI Read/Write operations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 16 ++++++++++++++++ drivers/media/dvb/mantis/mantis_link.h | 2 ++ 2 files changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 3368253aea6..b1e1aa0f5c1 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -92,6 +92,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) u32 hif_addr = 0, data, count = 4; dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num); + mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; hif_addr |= MANTIS_HIF_STATUS; @@ -104,9 +105,11 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) if (mantis_hif_sbuf_opdone_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); + mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } data = mmread(MANTIS_GPIF_DIN); + mutex_unlock(&ca->ca_lock); dprintk(verbose, MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data); return (data >> 24) & 0xff; } @@ -118,6 +121,7 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) u32 hif_addr = 0; dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num); + mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; @@ -130,9 +134,11 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) if (mantis_hif_write_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } dprintk(verbose, MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr); + mutex_unlock(&ca->ca_lock); return 0; } @@ -143,6 +149,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) u32 data, hif_addr = 0; dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num); + mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= MANTIS_HIF_STATUS; @@ -155,11 +162,13 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) if (mantis_hif_sbuf_opdone_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } data = mmread(MANTIS_GPIF_DIN); dprintk(verbose, MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); udelay(50); + mutex_unlock(&ca->ca_lock); return (u8) data; } @@ -170,6 +179,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) u32 hif_addr = 0; dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num); + mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr |= MANTIS_GPIF_PCMCIAIOM; @@ -181,9 +191,11 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) if (mantis_hif_write_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } dprintk(verbose, MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); + mutex_unlock(&ca->ca_lock); udelay(50); return 0; @@ -201,6 +213,7 @@ int mantis_hif_init(struct mantis_ca *ca) init_waitqueue_head(&ca->hif_opdone_wq); init_waitqueue_head(&ca->hif_write_wq); + mutex_lock(&ca->ca_lock); irqcfg = mmread(MANTIS_GPIF_IRQCFG); irqcfg = MANTIS_MASK_BRRDY | MANTIS_MASK_WRACK | @@ -210,6 +223,7 @@ int mantis_hif_init(struct mantis_ca *ca) MANTIS_MASK_OVFLW; mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); + mutex_unlock(&ca->ca_lock); return 0; } @@ -220,7 +234,9 @@ void mantis_hif_exit(struct mantis_ca *ca) u32 irqcfg; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num); + mutex_lock(&ca->ca_lock); irqcfg = mmread(MANTIS_GPIF_IRQCFG); irqcfg &= ~MANTIS_MASK_BRRDY; mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); + mutex_unlock(&ca->ca_lock); } diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 599ff1b57e4..f9aaaa52f52 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -21,6 +21,7 @@ #ifndef __MANTIS_LINK_H #define __MANTIS_LINK_H +#include #include #include "dvb_ca_en50221.h" @@ -61,6 +62,7 @@ struct mantis_ca { void *ca_priv; struct dvb_ca_en50221 en50221; + struct mutex ca_lock; }; /* CA */ -- cgit v1.2.3-70-g09d2 From 99b55b2c4478e6370aaa85173f5090a070c50a08 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:34:44 -0300 Subject: V4L/DVB (13789): [Mantis CA] Initialize the mutex Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 177b04813ff..53c01b3023c 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -156,6 +156,8 @@ int mantis_ca_init(struct mantis_pci *mantis) ca->en50221.poll_slot_status = mantis_slot_status; ca->en50221.data = ca; + mutex_init(&ca->ca_lock); + dprintk(verbose, MANTIS_ERROR, 1, "Registering EN50221 device"); if ((result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1)) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "EN50221: Initialization failed"); -- cgit v1.2.3-70-g09d2 From 42f541bfd1a9bad84a288d59a98fdb284df61a45 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:35:07 -0300 Subject: V4L/DVB (13790): [Mantis] Relocate queue initialization Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 4 ++++ drivers/media/dvb/mantis/mantis_hif.c | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 53c01b3023c..7aa27e0703b 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -158,6 +158,10 @@ int mantis_ca_init(struct mantis_pci *mantis) mutex_init(&ca->ca_lock); + init_waitqueue_head(&ca->hif_data_wq); + init_waitqueue_head(&ca->hif_opdone_wq); + init_waitqueue_head(&ca->hif_write_wq); + dprintk(verbose, MANTIS_ERROR, 1, "Registering EN50221 device"); if ((result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1)) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "EN50221: Initialization failed"); diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index b1e1aa0f5c1..99a9724cbaf 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -209,9 +209,6 @@ int mantis_hif_init(struct mantis_ca *ca) slot[0].slave_cfg = 0x70773028; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); - init_waitqueue_head(&ca->hif_data_wq); - init_waitqueue_head(&ca->hif_opdone_wq); - init_waitqueue_head(&ca->hif_write_wq); mutex_lock(&ca->ca_lock); irqcfg = mmread(MANTIS_GPIF_IRQCFG); -- cgit v1.2.3-70-g09d2 From 4af699c13a5fb7332255de5fa56442d065f547a3 Mon Sep 17 00:00:00 2001 From: Niklas Edmundsson Date: Fri, 4 Dec 2009 05:38:21 -0300 Subject: V4L/DVB (13791): [TDA10021] Do not claim TDA10023 Signed-off-by: Niklas Edmundsson Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda10021.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 6c1dbf9288d..6ca533ea0f0 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -426,6 +426,10 @@ struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, id = tda10021_readreg(state, 0x1a); if ((id & 0xf0) != 0x70) goto error; + /* Don't claim TDA10023 */ + if (id == 0x7d) + goto error; + printk("TDA10021: i2c-addr = 0x%02x, id = 0x%02x\n", state->config->demod_address, id); -- cgit v1.2.3-70-g09d2 From ec1b6ff1cce9d406a9a5f84a1d1205328f2c515a Mon Sep 17 00:00:00 2001 From: Niklas Edmundsson Date: Fri, 4 Dec 2009 05:38:52 -0300 Subject: V4L/DVB (13792): [Mantis/VP-2033] Do not claim TDA10023 Do not rely on the PCI ID alone Signed-off-by: Niklas Edmundsson Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 5172e856354..de18bb97d8e 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -263,30 +263,31 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; case MANTIS_VP_2033_DVB_C: // VP-2033 + case MANTIS_VP_2040_DVB_C: // VP-2040 + case TERRATEC_CINERGY_C_PCI: + case TECHNISAT_CABLESTAR_HD2: dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - mantis->fe = tda10021_attach(&philips_cu1216_config, &mantis->adapter, read_pwm(mantis)); + mantis->fe = tda10021_attach(&philips_cu1216_config, + &mantis->adapter, + read_pwm(mantis)); + if (mantis->fe) { - mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; dprintk(verbose, MANTIS_ERROR, 1, "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", philips_cu1216_config.demod_address); - - dprintk(verbose, MANTIS_ERROR, 1, - "Mantis DVB-C Philips CU1216 frontend attach success"); - + } else { + mantis->fe = tda10023_attach(&tda10023_cu1216_config, + &mantis->adapter, + read_pwm(mantis)); + + if (mantis->fe) { + dprintk(verbose, MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + philips_cu1216_config.demod_address); + } } - break; - case MANTIS_VP_2040_DVB_C: // VP-2040 - case TERRATEC_CINERGY_C_PCI: - case TECHNISAT_CABLESTAR_HD2: - dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - mantis->fe = tda10023_attach(&tda10023_cu1216_config, &mantis->adapter, read_pwm(mantis)); if (mantis->fe) { mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; - dprintk(verbose, MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", - philips_cu1216_config.demod_address); - dprintk(verbose, MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); } -- cgit v1.2.3-70-g09d2 From add206368462434ba97e8fe4de98e5d47ffdb0a0 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:39:57 -0300 Subject: V4L/DVB (13794): [Mantis/VP-3028] Initial go at Serial interface implementation, add support for VP-3028 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 2 + drivers/media/dvb/mantis/mantis_common.h | 10 +++ drivers/media/dvb/mantis/mantis_core.c | 8 ++ drivers/media/dvb/mantis/mantis_pci.c | 2 + drivers/media/dvb/mantis/mantis_uart.c | 139 +++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_uart.h | 25 +++++- drivers/media/dvb/mantis/mantis_vp1033.c | 3 + drivers/media/dvb/mantis/mantis_vp1034.c | 3 + drivers/media/dvb/mantis/mantis_vp1041.c | 3 + drivers/media/dvb/mantis/mantis_vp2033.c | 3 + drivers/media/dvb/mantis/mantis_vp2040.c | 3 + drivers/media/dvb/mantis/mantis_vp3028.c | 38 +++++++++ drivers/media/dvb/mantis/mantis_vp3028.h | 13 +++ drivers/media/dvb/mantis/mantis_vp3030.c | 3 + 14 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 drivers/media/dvb/mantis/mantis_uart.c create mode 100644 drivers/media/dvb/mantis/mantis_vp3028.c create mode 100644 drivers/media/dvb/mantis/mantis_vp3028.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index d002ef9f744..bb88cdc98ce 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -1,4 +1,5 @@ mantis-objs = mantis_core.o \ + mantis_uart.o \ mantis_dma.o \ mantis_pci.o \ mantis_i2c.o \ @@ -12,6 +13,7 @@ mantis-objs = mantis_core.o \ mantis_vp1041.o \ mantis_vp2033.o \ mantis_vp2040.o \ + mantis_vp3028.o \ mantis_vp3030.o obj-$(CONFIG_DVB_MANTIS) += mantis.o diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 6b9f92b4ab3..6a02adf1ab4 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "dvbdev.h" #include "dvb_demux.h" @@ -34,6 +35,7 @@ #include "dvb_net.h" #include #include "mantis_reg.h" +#include "mantis_uart.h" #include "mantis_link.h" @@ -74,6 +76,10 @@ struct mantis_hwconfig { char *model_name; char *dev_type; u32 ts_size; + + enum mantis_baud baud_rate; + enum mantis_parity parity; + u32 bytes; }; struct mantis_pci { @@ -142,6 +148,10 @@ struct mantis_pci { u32 gpif_status; struct mantis_ca *mantis_ca; + + wait_queue_head_t uart_wq; + struct work_struct uart_work; + spinlock_t uart_lock; }; #define MANTIS_HIF_STATUS (mantis->gpio_status) diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index c3d0d53bc38..52b3e9ebfcf 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -165,6 +165,10 @@ int mantis_core_init(struct mantis_pci *mantis) dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed"); return err; } + if ((err = mantis_uart_init(mantis)) < 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis UART init failed"); + return err; + } return 0; } @@ -173,6 +177,10 @@ int mantis_core_exit(struct mantis_pci *mantis) { mantis_dma_stop(mantis); dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping"); + + mantis_uart_exit(mantis); + dprintk(verbose, MANTIS_ERROR, 1, "UART exit failed"); + if (mantis_dma_exit(mantis) < 0) dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); if (mantis_dvb_exit(mantis) < 0) diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 94abcee3fc7..d1eac4083fc 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -27,6 +27,7 @@ #include #include "mantis_common.h" #include "mantis_core.h" +#include "mantis_uart.h" #include #include @@ -94,6 +95,7 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) } if (stat & MANTIS_INT_IRQ1) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); + schedule_work(&mantis->uart_work); } if (stat & MANTIS_INT_OCERR) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT OCERR *"); diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c new file mode 100644 index 00000000000..786fcc33911 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_uart.c @@ -0,0 +1,139 @@ +#include +#include "mantis_common.h" + +struct mantis_uart_params { + enum mantis_baud baud_rate; + enum mantis_parity parity; +}; + +#define UART_MAX_BUF 16 + +int mantis_uart_read(struct mantis_pci *mantis, u8 *data) +{ + struct mantis_hwconfig *config = mantis->hwconfig; + u32 stat, i; + unsigned long flags; + + /* get data */ + for (i = 0; i < (config->bytes + 1); i++) { + + if (stat & MANTIS_UART_RXFIFO_FULL) { + dprintk(verbose, MANTIS_ERROR, 1, "RX Fifo FULL"); + } + data[i] = mmread(MANTIS_UART_RXD) & 0x3f; + + stat = mmread(MANTIS_UART_STAT); + + dprintk(verbose, MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f); + + if (data[i] & (1 << 7)) { + dprintk(verbose, MANTIS_ERROR, 1, "UART framing error"); + return -EINVAL; + } + if (data[i] & (1 << 6)) { + dprintk(verbose, MANTIS_ERROR, 1, "UART parity error"); + return -EINVAL; + } + } + + return 0; +} + +static void mantis_uart_work(struct work_struct *work) +{ + struct mantis_pci *mantis = container_of(work, struct mantis_pci, uart_work); + struct mantis_hwconfig *config = mantis->hwconfig; + u8 buf[16]; + int i; + + dprintk(verbose, MANTIS_DEBUG, 1, "UART read"); + mantis_uart_read(mantis, buf); + + dprintk(verbose, MANTIS_DEBUG, 1, "UART: "); + for (i = 0; i < (config->bytes + 1); i++) + dprintk(verbose, MANTIS_DEBUG, 0, "<%02x> ", buf[i]); + + dprintk(verbose, MANTIS_DEBUG, 0, "\n"); +} + +static int mantis_uart_setup(struct mantis_pci *mantis, + struct mantis_uart_params *params) +{ + char* rates[] = { "B_9600", "B_19200", "B_38400", "B_57600", "B_115200" }; + char* parity[] = { "NONE", "ODD", "EVEN" }; + + u32 reg; + + dprintk(verbose, MANTIS_DEBUG, 1, "Set Parity <%s> Baud Rate <%s>", + parity[params->parity], + rates[params->baud_rate]); + + mmwrite((mmread(MANTIS_UART_CTL) | (params->parity & 0x3)), MANTIS_UART_CTL); + + reg = mmread(MANTIS_UART_BAUD); + + switch (params->baud_rate) { + case MANTIS_BAUD_9600: + reg |= 0xd8; + break; + case MANTIS_BAUD_19200: + reg |= 0x6c; + break; + case MANTIS_BAUD_38400: + reg |= 0x36; + break; + case MANTIS_BAUD_57600: + reg |= 0x23; + break; + case MANTIS_BAUD_115200: + reg |= 0x11; + break; + default: + return -EINVAL; + } + + mmwrite(reg, MANTIS_UART_BAUD); + + return 0; +} + +int mantis_uart_init(struct mantis_pci *mantis) +{ + struct mantis_hwconfig *config = mantis->hwconfig; + struct mantis_uart_params params; + + dprintk(verbose, MANTIS_DEBUG, 1, "Initializing UART .."); + /* default parity: */ + params.baud_rate = config->baud_rate; + params.parity = config->parity; + + init_waitqueue_head(&mantis->uart_wq); + spin_lock_init(&mantis->uart_lock); + + INIT_WORK(&mantis->uart_work, mantis_uart_work); + + /* disable interrupt */ + mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL); + + mantis_uart_setup(mantis, ¶ms); + + /* default 1 byte */ + mmwrite((mmread(MANTIS_UART_BAUD) | (config->bytes << 8)), MANTIS_UART_BAUD); + + /* flush buffer */ + mmwrite((mmread(MANTIS_UART_CTL) | MANTIS_UART_RXFLUSH), MANTIS_UART_CTL); + + /* enable interrupt */ + mmwrite(mmread(MANTIS_INT_MASK) | 0x800, MANTIS_INT_MASK); + mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL); + + schedule_work(&mantis->uart_work); + + return 0; +} + +void mantis_uart_exit(struct mantis_pci *mantis) +{ + /* disable interrupt */ + mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL); +} diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h index 61138639c36..e9f938d37c3 100644 --- a/drivers/media/dvb/mantis/mantis_uart.h +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -21,6 +21,21 @@ #ifndef __MANTIS_UART_H #define __MANTIS_UART_H +#define MANTIS_UART_CTL 0xe0 +#define MANTIS_UART_RXINT (1 << 4) +#define MANTIS_UART_RXFLUSH (1 << 2) + +#define MANTIS_UART_RXD 0xe8 +#define MANTIS_UART_BAUD 0xec + +#define MANTIS_UART_STAT 0xf0 +#define MANTIS_UART_RXFIFO_DATA (1 << 7) +#define MANTIS_UART_RXFIFO_EMPTY (1 << 6) +#define MANTIS_UART_RXFIFO_FULL (1 << 3) +#define MANTIS_UART_FRAME_ERR (1 << 2) +#define MANTIS_UART_PARITY_ERR (1 << 1) +#define MANTIS_UART_RXTHRESH_INT (1 << 0) + enum mantis_baud { MANTIS_BAUD_9600 = 0, MANTIS_BAUD_19200, @@ -30,9 +45,15 @@ enum mantis_baud { }; enum mantis_parity { - MANTIS_PARITY_NONE = 0, + MANTIS_PARITY_UNDEFINED = 0, MANTIS_PARITY_EVEN, - MANTIS_PARITY_ODD + MANTIS_PARITY_ODD, + MANTIS_PARITY_NONE }; +struct mantis_pci; + +extern int mantis_uart_init(struct mantis_pci *mantis); +extern void mantis_uart_exit(struct mantis_pci *mantis); + #endif // __MANTIS_UART_H diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 797c4e0c7ea..64cdfb8b709 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -88,6 +88,9 @@ struct mantis_hwconfig vp1033_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_204, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index a2fe9d42d1e..28f3420b231 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -33,6 +33,9 @@ struct mantis_hwconfig vp1034_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_204, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 8eb1afdab11..90df80b80e1 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -31,6 +31,9 @@ struct mantis_hwconfig vp1041_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_188, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 4664d295921..1171e69b7e6 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -28,6 +28,9 @@ struct mantis_hwconfig vp2033_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_204, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; struct tda1002x_config philips_cu1216_config = { diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index f77be7b6491..ce73d6beb5c 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -28,6 +28,9 @@ struct mantis_hwconfig vp2040_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_204, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; struct tda10023_config tda10023_cu1216_config = { diff --git a/drivers/media/dvb/mantis/mantis_vp3028.c b/drivers/media/dvb/mantis/mantis_vp3028.c new file mode 100644 index 00000000000..7f8918c2ce6 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3028.c @@ -0,0 +1,38 @@ +/* + Mantis VP-3028 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp3028.h" + +struct zl10353_config mantis_vp3028_config = { + .demod_address = 0x0f, +}; + +#define MANTIS_MODEL_NAME "VP-3028" +#define MANTIS_DEV_TYPE "DVB-T" + +struct mantis_hwconfig vp3028_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp3028.h b/drivers/media/dvb/mantis/mantis_vp3028.h new file mode 100644 index 00000000000..c51628ddf3c --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3028.h @@ -0,0 +1,13 @@ +#ifndef __MANTIS_VP3028_H +#define __MANTIS_VP3028_H + +#include "dvb_frontend.h" +#include "mantis_common.h" +#include "zl10353.h" + +#define MANTIS_VP_3028_DVB_T 0x0028 + +extern struct zl10353_config mantis_vp3028_config; +extern struct mantis_hwconfig vp3028_mantis_config; + +#endif /* __MANTIS_VP3028_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index cab092ce230..9ca8040489d 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -32,6 +32,9 @@ struct mantis_hwconfig vp3030_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_188, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, -- cgit v1.2.3-70-g09d2 From b3b961448f702339444036f94252ff2ba7a99feb Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:41:11 -0300 Subject: V4L/DVB (13795): [Mantis/Hopper] Code overhaul, add Hopper devices into the PCI ID list Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Kconfig | 22 +- drivers/media/dvb/mantis/Makefile | 42 ++-- drivers/media/dvb/mantis/hopper_cards.c | 260 ++++++++++++++++++++++ drivers/media/dvb/mantis/hopper_vp3028.c | 76 +++++++ drivers/media/dvb/mantis/hopper_vp3028.h | 10 + drivers/media/dvb/mantis/mantis_ca.c | 69 +++--- drivers/media/dvb/mantis/mantis_ca.h | 7 + drivers/media/dvb/mantis/mantis_cards.c | 279 +++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_common.h | 68 +++--- drivers/media/dvb/mantis/mantis_dma.c | 55 +++-- drivers/media/dvb/mantis/mantis_dma.h | 10 + drivers/media/dvb/mantis/mantis_dvb.c | 364 ++++++++++++++----------------- drivers/media/dvb/mantis/mantis_dvb.h | 15 ++ drivers/media/dvb/mantis/mantis_evm.c | 38 +++- drivers/media/dvb/mantis/mantis_hif.c | 60 +++-- drivers/media/dvb/mantis/mantis_hif.h | 2 +- drivers/media/dvb/mantis/mantis_i2c.c | 75 ++++--- drivers/media/dvb/mantis/mantis_i2c.h | 7 + drivers/media/dvb/mantis/mantis_ioc.c | 145 ++++++++++++ drivers/media/dvb/mantis/mantis_link.h | 3 +- drivers/media/dvb/mantis/mantis_pci.c | 310 +++++++++----------------- drivers/media/dvb/mantis/mantis_pci.h | 7 + drivers/media/dvb/mantis/mantis_pcmcia.c | 22 +- drivers/media/dvb/mantis/mantis_reg.h | 40 +++- drivers/media/dvb/mantis/mantis_uart.c | 37 +++- drivers/media/dvb/mantis/mantis_uart.h | 2 +- drivers/media/dvb/mantis/mantis_vp1033.c | 98 ++++++--- drivers/media/dvb/mantis/mantis_vp1033.h | 13 +- drivers/media/dvb/mantis/mantis_vp1034.c | 66 ++++-- drivers/media/dvb/mantis/mantis_vp1034.h | 6 +- drivers/media/dvb/mantis/mantis_vp1041.c | 79 ++++++- drivers/media/dvb/mantis/mantis_vp1041.h | 14 +- drivers/media/dvb/mantis/mantis_vp2033.c | 95 ++++++-- drivers/media/dvb/mantis/mantis_vp2033.h | 11 +- drivers/media/dvb/mantis/mantis_vp2040.c | 141 +++++++++++- drivers/media/dvb/mantis/mantis_vp2040.h | 11 +- drivers/media/dvb/mantis/mantis_vp3030.c | 49 ++++- drivers/media/dvb/mantis/mantis_vp3030.h | 8 +- 38 files changed, 1881 insertions(+), 735 deletions(-) create mode 100644 drivers/media/dvb/mantis/hopper_cards.c create mode 100644 drivers/media/dvb/mantis/hopper_vp3028.c create mode 100644 drivers/media/dvb/mantis/hopper_vp3028.h create mode 100644 drivers/media/dvb/mantis/mantis_ca.h create mode 100644 drivers/media/dvb/mantis/mantis_cards.c create mode 100644 drivers/media/dvb/mantis/mantis_dma.h create mode 100644 drivers/media/dvb/mantis/mantis_dvb.h create mode 100644 drivers/media/dvb/mantis/mantis_i2c.h create mode 100644 drivers/media/dvb/mantis/mantis_ioc.c create mode 100644 drivers/media/dvb/mantis/mantis_pci.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig index 4ba16d0ad96..aaf025097b4 100644 --- a/drivers/media/dvb/mantis/Kconfig +++ b/drivers/media/dvb/mantis/Kconfig @@ -1,6 +1,15 @@ +config MANTIS_CORE + tristate "Mantis/Hopper PCI bridge based devices" + depends on PCI && I2C + + help + Support for PCI cards based on the Mantis and Hopper PCi bridge. + + Say Y if you own such a device and want to use it. + config DVB_MANTIS tristate "MANTIS based cards" - depends on DVB_CORE && PCI && I2C + depends on MANTIS_CORE && DVB_CORE && PCI && I2C select DVB_MB86A16 select DVB_CU1216 select DVB_ZL10353 @@ -11,3 +20,14 @@ config DVB_MANTIS Say Y when you have a Mantis based DVB card and want to use it. If unsure say N. + +config DVB_HOPPER + tristate "HOPPER based cards" + depends on MANTIS_CORE && DVB_CORE && PCI && I2C + select DVB_ZL10353 + select DVB_PLL + help + Support for PCI cards based on the Hopper PCI bridge. + Say Y when you have a Hopper based DVB card and want to use it. + + If unsure say N diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index bb88cdc98ce..399c9018cdb 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -1,21 +1,27 @@ -mantis-objs = mantis_core.o \ - mantis_uart.o \ - mantis_dma.o \ - mantis_pci.o \ - mantis_i2c.o \ - mantis_dvb.o \ - mantis_evm.o \ - mantis_hif.o \ - mantis_ca.o \ - mantis_pcmcia.o \ - mantis_vp1033.o \ - mantis_vp1034.o \ - mantis_vp1041.o \ - mantis_vp2033.o \ - mantis_vp2040.o \ - mantis_vp3028.o \ - mantis_vp3030.o +mantis_core-objs := mantis_ioc.o \ + mantis_uart.o \ + mantis_dma.o \ + mantis_pci.o \ + mantis_i2c.o \ + mantis_dvb.o \ + mantis_evm.o \ + mantis_hif.o \ + mantis_ca.o \ + mantis_pcmcia.o -obj-$(CONFIG_DVB_MANTIS) += mantis.o +mantis-objs := mantis_cards.o \ + mantis_vp1033.o \ + mantis_vp1034.o \ + mantis_vp1041.o \ + mantis_vp2033.o \ + mantis_vp2040.o \ + mantis_vp3030.o + +hopper-objs := hopper_cards.o \ + hopper_vp3028.o + +obj-$(CONFIG_MANTIS_CORE) += mantis_core.o +obj-$(CONFIG_DVB_MANTIS) += mantis.o +obj-$(CONFIG_DVB_HOPPER) += hopper.o EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c new file mode 100644 index 00000000000..749e3f3dd06 --- /dev/null +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "mantis_common.h" +#include "hopper_vp3028.h" +#include "mantis_dma.h" +#include "mantis_dvb.h" +#include "mantis_uart.h" +#include "mantis_ioc.h" +#include "mantis_pci.h" +#include "mantis_i2c.h" +#include "mantis_reg.h" + +static unsigned int verbose; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); + +#define DRIVER_NAME "Hopper" + +static char *label[10] = { + "DMA", + "IRQ-0", + "IRQ-1", + "OCERR", + "PABRT", + "RIPRR", + "PPERR", + "FTRGT", + "RISCI", + "RACK" +}; + +static int devs; + +static irqreturn_t hopper_irq_handler(int irq, void *dev_id) +{ + u32 stat = 0, mask = 0, lstat = 0, mstat = 0; + u32 rst_stat = 0, rst_mask = 0; + + struct mantis_pci *mantis; + struct mantis_ca *ca; + + mantis = (struct mantis_pci *) dev_id; + if (unlikely(mantis == NULL)) { + dprintk(MANTIS_ERROR, 1, "Mantis == NULL"); + return IRQ_NONE; + } + ca = mantis->mantis_ca; + + stat = mmread(MANTIS_INT_STAT); + mask = mmread(MANTIS_INT_MASK); + mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; + if (!(stat & mask)) + return IRQ_NONE; + + rst_mask = MANTIS_GPIF_WRACK | + MANTIS_GPIF_OTHERR | + MANTIS_SBUF_WSTO | + MANTIS_GPIF_EXTIRQ; + + rst_stat = mmread(MANTIS_GPIF_STATUS); + rst_stat &= rst_mask; + mmwrite(rst_stat, MANTIS_GPIF_STATUS); + + mantis->mantis_int_stat = stat; + mantis->mantis_int_mask = mask; + dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask); + if (stat & MANTIS_INT_RISCEN) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]); + } + if (stat & MANTIS_INT_IRQ0) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]); + mantis->gpif_status = rst_stat; + wake_up(&ca->hif_write_wq); + schedule_work(&ca->hif_evm_work); + } + if (stat & MANTIS_INT_IRQ1) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]); + schedule_work(&mantis->uart_work); + } + if (stat & MANTIS_INT_OCERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]); + } + if (stat & MANTIS_INT_PABORT) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]); + } + if (stat & MANTIS_INT_RIPERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]); + } + if (stat & MANTIS_INT_PPERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]); + } + if (stat & MANTIS_INT_FTRGT) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]); + } + if (stat & MANTIS_INT_RISCI) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); + mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; + tasklet_schedule(&mantis->tasklet); + } + if (stat & MANTIS_INT_I2CDONE) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]); + wake_up(&mantis->i2c_wq); + } + mmwrite(stat, MANTIS_INT_STAT); + stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | + MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | + MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | + MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | + MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | + MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | + MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | + MANTIS_INT_PABORT | MANTIS_INT_RIPERR | + MANTIS_INT_PPERR | MANTIS_INT_FTRGT | + MANTIS_INT_RISCI); + + if (stat) + dprintk(MANTIS_DEBUG, 0, " Stat=<%02x> Mask=<%02x>", stat, mask); + + dprintk(MANTIS_DEBUG, 0, "\n"); + return IRQ_HANDLED; +} + +static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) +{ + struct mantis_pci *mantis; + struct mantis_hwconfig *config; + int err = 0; + + mantis = kzalloc(sizeof (struct mantis_pci), GFP_KERNEL); + if (mantis == NULL) { + printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); + err = -ENOMEM; + goto fail0; + } + + mantis->num = devs; + mantis->verbose = verbose; + mantis->pdev = pdev; + config = (struct mantis_hwconfig *) pci_id->driver_data; + config->irq_handler = &hopper_irq_handler; + mantis->hwconfig = config; + + err = mantis_pci_init(mantis); + if (err) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err); + goto fail1; + } + + err = mantis_stream_control(mantis, STREAM_TO_HIF); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err); + goto fail1; + } + + err = mantis_i2c_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err); + goto fail2; + } + + err = mantis_get_mac(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err); + goto fail2; + } + + err = mantis_dma_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err); + goto fail3; + } + + err = mantis_dvb_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err); + goto fail4; + } + devs++; + + return err; + +fail5: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB exit! <%d>", err); + mantis_dvb_exit(mantis); + +fail4: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); + mantis_dma_exit(mantis); + +fail3: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err); + mantis_i2c_exit(mantis); + +fail2: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err); + mantis_pci_exit(mantis); + +fail1: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err); + kfree(mantis); + +fail0: + return err; +} + +static void __devexit hopper_pci_remove(struct pci_dev *pdev) +{ + struct mantis_pci *mantis = pci_get_drvdata(pdev); + + if (mantis) { +// mantis_uart_exit(mantis); + mantis_dvb_exit(mantis); + mantis_dma_exit(mantis); + mantis_i2c_exit(mantis); + mantis_pci_exit(mantis); + kfree(mantis); + } + return; + +} + +static struct pci_device_id hopper_pci_table[] = { + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config), + { } +}; + +static struct pci_driver hopper_pci_driver = { + .name = DRIVER_NAME, + .id_table = hopper_pci_table, + .probe = hopper_pci_probe, + .remove = hopper_pci_remove, +}; + +static int __devinit hopper_init(void) +{ + return pci_register_driver(&hopper_pci_driver); +} + +static void __devexit hopper_exit(void) +{ + return pci_unregister_driver(&hopper_pci_driver); +} + +module_init(hopper_init); +module_exit(hopper_exit); + +MODULE_DESCRIPTION("HOPPER driver"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c new file mode 100644 index 00000000000..ba0c7e58b7a --- /dev/null +++ b/drivers/media/dvb/mantis/hopper_vp3028.c @@ -0,0 +1,76 @@ +/* + Mantis VP-3028 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "zl10353.h" +#include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" +#include "hopper_vp3028.h" + +struct zl10353_config hopper_vp3028_config = { + .demod_address = 0x0f, +}; + +#define MANTIS_MODEL_NAME "VP-3028" +#define MANTIS_DEV_TYPE "DVB-T" + +static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + int err = 0; + + err = mantis_frontend_power(mantis, POWER_ON); + mantis_frontend_soft_reset(mantis); + + dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); + fe = zl10353_attach(&hopper_vp3028_config, adapter); + + if (!fe) + return -1; + + dprintk(MANTIS_ERROR, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp3028_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp3028_frontend_init, + .power = GPIF_A00, + .reset = GPIF_A03, +}; diff --git a/drivers/media/dvb/mantis/hopper_vp3028.h b/drivers/media/dvb/mantis/hopper_vp3028.h new file mode 100644 index 00000000000..e8a3c2297bb --- /dev/null +++ b/drivers/media/dvb/mantis/hopper_vp3028.h @@ -0,0 +1,10 @@ +#ifndef __MANTIS_VP3028_H +#define __MANTIS_VP3028_H + +#include "mantis_common.h" + +#define MANTIS_VP_3028_DVB_T 0x0028 + +extern struct mantis_hwconfig vp3028_config; + +#endif /* __MANTIS_VP3028_H */ diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 7aa27e0703b..4151cba35e7 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -18,16 +18,30 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" #include "mantis_link.h" #include "mantis_hif.h" +#include "mantis_reg.h" + +#include "mantis_ca.h" static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr) { struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot); if (slot != 0) return -EINVAL; @@ -40,7 +54,7 @@ static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, in struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot); if (slot != 0) return -EINVAL; @@ -53,7 +67,7 @@ static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 a struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot); if (slot != 0) return -EINVAL; @@ -66,7 +80,7 @@ static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot); if (slot != 0) return -EINVAL; @@ -79,7 +93,7 @@ static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot); udelay(500); /* Wait.. */ mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */ udelay(500); @@ -95,7 +109,7 @@ static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot); return 0; } @@ -105,8 +119,8 @@ static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); - mantis_set_direction(mantis, 1); /* Enable TS through CAM */ + dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); +// mantis_set_direction(mantis, 1); /* Enable TS through CAM */ return 0; } @@ -116,13 +130,13 @@ static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot); if (ca->slot_state == MODULE_INSERTED) { - dprintk(verbose, MANTIS_DEBUG, 1, "CA Module present and ready"); + dprintk(MANTIS_DEBUG, 1, "CA Module present and ready"); return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; } else { - dprintk(verbose, MANTIS_DEBUG, 1, "CA Module not present or not ready"); + dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready"); } return 0; @@ -130,20 +144,21 @@ static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open int mantis_ca_init(struct mantis_pci *mantis) { - struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter; + struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter; struct mantis_ca *ca; int ca_flags = 0, result; - dprintk(verbose, MANTIS_DEBUG, 1, "Initializing Mantis CA"); - if (!(ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL))) { - dprintk(verbose, MANTIS_ERROR, 1, "Out of memory!, exiting .."); + dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA"); + ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL); + if (!ca) { + dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting .."); result = -ENOMEM; goto err; } - ca->ca_priv = mantis; - mantis->mantis_ca = ca; - ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; + ca->ca_priv = mantis; + mantis->mantis_ca = ca; + ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; /* register CA interface */ ca->en50221.owner = THIS_MODULE; ca->en50221.read_attribute_mem = mantis_ca_read_attr_mem; @@ -162,28 +177,32 @@ int mantis_ca_init(struct mantis_pci *mantis) init_waitqueue_head(&ca->hif_opdone_wq); init_waitqueue_head(&ca->hif_write_wq); - dprintk(verbose, MANTIS_ERROR, 1, "Registering EN50221 device"); - if ((result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1)) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "EN50221: Initialization failed"); + dprintk(MANTIS_ERROR, 1, "Registering EN50221 device"); + result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1); + if (result != 0) { + dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result); goto err; } - dprintk(verbose, MANTIS_ERROR, 1, "Registered EN50221 device"); + dprintk(MANTIS_ERROR, 1, "Registered EN50221 device"); mantis_evmgr_init(ca); return 0; err: kfree(ca); return result; } +EXPORT_SYMBOL_GPL(mantis_ca_init); void mantis_ca_exit(struct mantis_pci *mantis) { struct mantis_ca *ca = mantis->mantis_ca; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis CA exit"); + dprintk(MANTIS_DEBUG, 1, "Mantis CA exit"); mantis_evmgr_exit(ca); - dprintk(verbose, MANTIS_ERROR, 1, "Unregistering EN50221 device"); - dvb_ca_en50221_release(&ca->en50221); + dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device"); + if (ca) + dvb_ca_en50221_release(&ca->en50221); kfree(ca); } +EXPORT_SYMBOL_GPL(mantis_ca_exit); diff --git a/drivers/media/dvb/mantis/mantis_ca.h b/drivers/media/dvb/mantis/mantis_ca.h new file mode 100644 index 00000000000..b7e48ee1fac --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ca.h @@ -0,0 +1,7 @@ +#ifndef __MANTIS_CA_H +#define __MANTIS_CA_H + +extern int mantis_ca_init(struct mantis_pci *mantis); +extern void mantis_ca_exit(struct mantis_pci *mantis); + +#endif /* __MANTIS_CA_H */ diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c new file mode 100644 index 00000000000..d486c7fcb45 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -0,0 +1,279 @@ +#include +#include +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "mantis_common.h" + +#include "mantis_vp1033.h" +#include "mantis_vp1034.h" +#include "mantis_vp1041.h" +#include "mantis_vp2033.h" +#include "mantis_vp2040.h" +#include "mantis_vp3030.h" + +#include "mantis_dma.h" +#include "mantis_ca.h" +#include "mantis_dvb.h" +#include "mantis_uart.h" +#include "mantis_ioc.h" +#include "mantis_pci.h" +#include "mantis_i2c.h" +#include "mantis_reg.h" + +static unsigned int verbose; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); + +static int devs; + +#define DRIVER_NAME "Mantis" + +static char *label[10] = { + "DMA", + "IRQ-0", + "IRQ-1", + "OCERR", + "PABRT", + "RIPRR", + "PPERR", + "FTRGT", + "RISCI", + "RACK" +}; + + +static irqreturn_t mantis_irq_handler(int irq, void *dev_id) +{ + u32 stat = 0, mask = 0, lstat = 0, mstat = 0; + u32 rst_stat = 0, rst_mask = 0; + + struct mantis_pci *mantis; + struct mantis_ca *ca; + + mantis = (struct mantis_pci *) dev_id; + if (unlikely(mantis == NULL)) { + dprintk(MANTIS_ERROR, 1, "Mantis == NULL"); + return IRQ_NONE; + } + ca = mantis->mantis_ca; + + stat = mmread(MANTIS_INT_STAT); + mask = mmread(MANTIS_INT_MASK); + mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; + if (!(stat & mask)) + return IRQ_NONE; + + rst_mask = MANTIS_GPIF_WRACK | + MANTIS_GPIF_OTHERR | + MANTIS_SBUF_WSTO | + MANTIS_GPIF_EXTIRQ; + + rst_stat = mmread(MANTIS_GPIF_STATUS); + rst_stat &= rst_mask; + mmwrite(rst_stat, MANTIS_GPIF_STATUS); + + mantis->mantis_int_stat = stat; + mantis->mantis_int_mask = mask; + dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask); + if (stat & MANTIS_INT_RISCEN) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]); + } + if (stat & MANTIS_INT_IRQ0) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]); + mantis->gpif_status = rst_stat; + wake_up(&ca->hif_write_wq); + schedule_work(&ca->hif_evm_work); + } + if (stat & MANTIS_INT_IRQ1) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]); + schedule_work(&mantis->uart_work); + } + if (stat & MANTIS_INT_OCERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]); + } + if (stat & MANTIS_INT_PABORT) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]); + } + if (stat & MANTIS_INT_RIPERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]); + } + if (stat & MANTIS_INT_PPERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]); + } + if (stat & MANTIS_INT_FTRGT) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]); + } + if (stat & MANTIS_INT_RISCI) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); + mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; + tasklet_schedule(&mantis->tasklet); + } + if (stat & MANTIS_INT_I2CDONE) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]); + wake_up(&mantis->i2c_wq); + } + mmwrite(stat, MANTIS_INT_STAT); + stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | + MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | + MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | + MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | + MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | + MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | + MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | + MANTIS_INT_PABORT | MANTIS_INT_RIPERR | + MANTIS_INT_PPERR | MANTIS_INT_FTRGT | + MANTIS_INT_RISCI); + + if (stat) + dprintk(MANTIS_DEBUG, 0, " Stat=<%02x> Mask=<%02x>", stat, mask); + + dprintk(MANTIS_DEBUG, 0, "\n"); + return IRQ_HANDLED; +} + +static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) +{ + struct mantis_pci *mantis; + struct mantis_hwconfig *config; + int err = 0; + + mantis = kzalloc(sizeof (struct mantis_pci), GFP_KERNEL); + if (mantis == NULL) { + printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); + err = -ENOMEM; + goto fail0; + } + + mantis->num = devs; + mantis->verbose = verbose; + mantis->pdev = pdev; + config = (struct mantis_hwconfig *) pci_id->driver_data; + config->irq_handler = &mantis_irq_handler; + mantis->hwconfig = config; + + err = mantis_pci_init(mantis); + if (err) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err); + goto fail1; + } + + err = mantis_stream_control(mantis, STREAM_TO_HIF); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err); + goto fail1; + } + + err = mantis_i2c_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err); + goto fail2; + } + + err = mantis_get_mac(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err); + goto fail2; + } + + err = mantis_dma_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err); + goto fail3; + } + + err = mantis_dvb_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err); + goto fail4; + } + devs++; + + return err; + +fail5: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB exit! <%d>", err); + mantis_dvb_exit(mantis); + +fail4: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); + mantis_dma_exit(mantis); + +fail3: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err); + mantis_i2c_exit(mantis); + +fail2: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err); + mantis_pci_exit(mantis); + +fail1: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err); + kfree(mantis); + +fail0: + return err; +} + +static void __devexit mantis_pci_remove(struct pci_dev *pdev) +{ + struct mantis_pci *mantis = pci_get_drvdata(pdev); + + if (mantis) { + mantis_uart_exit(mantis); +// mantis_ca_exit(mantis); + mantis_dvb_exit(mantis); + mantis_dma_exit(mantis); + mantis_i2c_exit(mantis); + mantis_pci_exit(mantis); + kfree(mantis); + } + return; +} + +static struct pci_device_id mantis_pci_table[] = { + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1033_DVB_S, &vp1033_config), + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1034_DVB_S, &vp1034_config), + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1041_DVB_S2, &vp1041_config), + MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_10, &vp1041_config), + MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_20, &vp1041_config), + MAKE_ENTRY(TERRATEC, CINERGY_S2_PCI_HD, &vp1041_config), + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config), + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config), + MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config), + MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2033_config), + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config), + { } +}; + +static struct pci_driver mantis_pci_driver = { + .name = DRIVER_NAME, + .id_table = mantis_pci_table, + .probe = mantis_pci_probe, + .remove = mantis_pci_remove, +}; + +static int __devinit mantis_init(void) +{ + return pci_register_driver(&mantis_pci_driver); +} + +static void __devexit mantis_exit(void) +{ + return pci_unregister_driver(&mantis_pci_driver); +} + +module_init(mantis_init); +module_exit(mantis_exit); + +MODULE_DESCRIPTION("MANTIS driver"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 6a02adf1ab4..e912c5962e3 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -21,20 +21,9 @@ #ifndef __MANTIS_COMMON_H #define __MANTIS_COMMON_H -#include -#include -#include -#include #include #include -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dmxdev.h" -#include "dvb_frontend.h" -#include "dvb_net.h" -#include -#include "mantis_reg.h" #include "mantis_uart.h" #include "mantis_link.h" @@ -44,18 +33,18 @@ #define MANTIS_INFO 2 #define MANTIS_DEBUG 3 -#define dprintk(x, y, z, format, arg...) do { \ +#define dprintk(y, z, format, arg...) do { \ if (z) { \ - if ((x > MANTIS_ERROR) && (x > y)) \ + if ((mantis->verbose > MANTIS_ERROR) && (mantis->verbose > y)) \ printk(KERN_ERR "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ - else if ((x > MANTIS_NOTICE) && (x > y)) \ + else if ((mantis->verbose > MANTIS_NOTICE) && (mantis->verbose > y)) \ printk(KERN_NOTICE "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ - else if ((x > MANTIS_INFO) && (x > y)) \ + else if ((mantis->verbose > MANTIS_INFO) && (mantis->verbose > y)) \ printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ - else if ((x > MANTIS_DEBUG) && (x > y)) \ + else if ((mantis->verbose > MANTIS_DEBUG) && (mantis->verbose > y)) \ printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ } else { \ - if (x > y) \ + if (mantis->verbose > y) \ printk(format , ##arg); \ } \ } while(0) @@ -63,8 +52,8 @@ #define mwrite(dat, addr) writel((dat), addr) #define mread(addr) readl(addr) -#define mmwrite(dat, addr) mwrite((dat), (mantis->mantis_mmio + (addr))) -#define mmread(addr) mread(mantis->mantis_mmio + (addr)) +#define mmwrite(dat, addr) mwrite((dat), (mantis->mmio + (addr))) +#define mmread(addr) mread(mantis->mmio + (addr)) #define mmand(dat, addr) mmwrite((dat) & mmread(addr), addr) #define mmor(dat, addr) mmwrite((dat) | mmread(addr), addr) #define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr) @@ -72,6 +61,22 @@ #define MANTIS_TS_188 0 #define MANTIS_TS_204 1 +#define TWINHAN_TECHNOLOGIES 0x1822 +#define MANTIS 0x4e35 + +#define TECHNISAT 0x1ae4 +#define TERRATEC 0x153b + +#define MAKE_ENTRY(__subven, __subdev, __configptr) { \ + .vendor = TWINHAN_TECHNOLOGIES, \ + .device = MANTIS, \ + .subvendor = (__subven), \ + .subdevice = (__subdev), \ + .driver_data = (unsigned long) (__configptr) \ +} + +struct mantis_pci; + struct mantis_hwconfig { char *model_name; char *dev_type; @@ -80,6 +85,12 @@ struct mantis_hwconfig { enum mantis_baud baud_rate; enum mantis_parity parity; u32 bytes; + + irqreturn_t (*irq_handler)(int irq, void *dev_id); + int (*frontend_init)(struct mantis_pci *mantis, struct dvb_frontend *fe); + + u8 power; + u8 reset; }; struct mantis_pci { @@ -96,7 +107,7 @@ struct mantis_pci { struct pci_dev *pdev; unsigned long mantis_addr; - volatile void __iomem *mantis_mmio; + void __iomem *mmio; u8 irq; u8 revision; @@ -156,19 +167,4 @@ struct mantis_pci { #define MANTIS_HIF_STATUS (mantis->gpio_status) -extern unsigned int verbose; -extern unsigned int devs; -extern unsigned int i2c; -extern int mantis_dvb_init(struct mantis_pci *mantis); -extern int mantis_frontend_init(struct mantis_pci *mantis); -extern int mantis_dvb_exit(struct mantis_pci *mantis); -extern void mantis_dma_xfer(unsigned long data); -extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); - -extern void mantis_set_direction(struct mantis_pci *mantis, int direction); - -extern int mantis_ca_init(struct mantis_pci *mantis); -extern void mantis_ca_exit(struct mantis_pci *mantis); - - -#endif //__MANTIS_COMMON_H +#endif /* __MANTIS_COMMON_H */ diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index d15a1eb980c..8ebcd96b2b7 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -18,9 +18,25 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include +#include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_dma.h" #define RISC_WRITE (0x01 << 28) #define RISC_JUMP (0x07 << 28) @@ -38,7 +54,7 @@ int mantis_dma_exit(struct mantis_pci *mantis) { if (mantis->buf_cpu) { - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "DMA=0x%lx cpu=0x%p size=%d", (unsigned long) mantis->buf_dma, mantis->buf_cpu, @@ -50,7 +66,7 @@ int mantis_dma_exit(struct mantis_pci *mantis) mantis->buf_cpu = NULL; } if (mantis->risc_cpu) { - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "RISC=0x%lx cpu=0x%p size=%lx", (unsigned long) mantis->risc_dma, mantis->risc_cpu, @@ -64,6 +80,7 @@ int mantis_dma_exit(struct mantis_pci *mantis) return 0; } +EXPORT_SYMBOL_GPL(mantis_dma_exit); static inline int mantis_alloc_buffers(struct mantis_pci *mantis) { @@ -72,12 +89,12 @@ static inline int mantis_alloc_buffers(struct mantis_pci *mantis) MANTIS_BUF_SIZE, &mantis->buf_dma); if (!mantis->buf_cpu) { - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "DMA buffer allocation failed"); goto err; } - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "DMA=0x%lx cpu=0x%p size=%d", (unsigned long) mantis->buf_dma, mantis->buf_cpu, MANTIS_BUF_SIZE); @@ -88,14 +105,14 @@ static inline int mantis_alloc_buffers(struct mantis_pci *mantis) &mantis->risc_dma); if (!mantis->risc_cpu) { - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "RISC program allocation failed"); mantis_dma_exit(mantis); goto err; } - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "RISC=0x%lx cpu=0x%p size=%lx", (unsigned long) mantis->risc_dma, mantis->risc_cpu, MANTIS_RISC_SIZE); @@ -103,7 +120,7 @@ static inline int mantis_alloc_buffers(struct mantis_pci *mantis) return 0; err: - dprintk(verbose, MANTIS_ERROR, 1, "Out of memory (?) ....."); + dprintk(MANTIS_ERROR, 1, "Out of memory (?) ....."); return -ENOMEM; } @@ -117,12 +134,11 @@ static inline int mantis_calc_lines(struct mantis_pci *mantis) mantis->line_count <<= 1; } - dprintk(verbose, MANTIS_DEBUG, 1, - "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]", + dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]", MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count); if (mantis->line_count > 255) { - dprintk(verbose, MANTIS_ERROR, 1, "Buffer size error"); + dprintk(MANTIS_ERROR, 1, "Buffer size error"); return -EINVAL; } @@ -133,9 +149,9 @@ int mantis_dma_init(struct mantis_pci *mantis) { int err = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DMA init"); + dprintk(MANTIS_DEBUG, 1, "Mantis DMA init"); if (mantis_alloc_buffers(mantis) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Error allocating DMA buffer"); + dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer"); // Stop RISC Engine // mmwrite(mmread(MANTIS_DMA_CTL) & ~MANTIS_RISC_EN, MANTIS_DMA_CTL); @@ -144,7 +160,7 @@ int mantis_dma_init(struct mantis_pci *mantis) goto err; } if ((err = mantis_calc_lines(mantis)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis calc lines failed"); + dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed"); goto err; } @@ -153,20 +169,21 @@ int mantis_dma_init(struct mantis_pci *mantis) err: return err; } +EXPORT_SYMBOL_GPL(mantis_dma_init); static inline void mantis_risc_program(struct mantis_pci *mantis) { u32 buf_pos = 0; u32 line; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis create RISC program"); + dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program"); RISC_FLUSH(); - dprintk(verbose, MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u", + dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u", mantis->line_count, mantis->line_bytes); for (line = 0; line < mantis->line_count; line++) { - dprintk(verbose, MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line); + dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line); if (!(buf_pos % MANTIS_BLOCK_BYTES)) { RISC_INSTR(RISC_WRITE | RISC_IRQ | @@ -186,7 +203,7 @@ static inline void mantis_risc_program(struct mantis_pci *mantis) void mantis_dma_start(struct mantis_pci *mantis) { - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Start DMA engine"); + dprintk(MANTIS_DEBUG, 1, "Mantis Start DMA engine"); mantis_risc_program(mantis); mmwrite(mantis->risc_dma, MANTIS_RISC_START); @@ -208,7 +225,7 @@ void mantis_dma_stop(struct mantis_pci *mantis) stat = mmread(MANTIS_INT_STAT); mask = mmread(MANTIS_INT_MASK); - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); + dprintk(MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR); @@ -229,7 +246,7 @@ void mantis_dma_xfer(unsigned long data) struct mantis_hwconfig *config = mantis->hwconfig; while (mantis->last_block != mantis->finished_block) { - dprintk(verbose, MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", + dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", mantis->last_block, mantis->finished_block); (config->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) diff --git a/drivers/media/dvb/mantis/mantis_dma.h b/drivers/media/dvb/mantis/mantis_dma.h new file mode 100644 index 00000000000..4cba8763536 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dma.h @@ -0,0 +1,10 @@ +#ifndef __MANTIS_DMA_H +#define __MANTIS_DMA_H + +extern int mantis_dma_init(struct mantis_pci *mantis); +extern int mantis_dma_exit(struct mantis_pci *mantis); +extern void mantis_dma_start(struct mantis_pci *mantis); +extern void mantis_dma_stop(struct mantis_pci *mantis); +extern void mantis_dma_xfer(unsigned long data); + +#endif /* __MANTIS_DMA_H */ diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index de18bb97d8e..be911d76daa 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -17,65 +17,86 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include -#include "mantis_common.h" -#include "mantis_core.h" + +#include +#include +#include +#include +#include +#include #include "dmxdev.h" #include "dvbdev.h" #include "dvb_demux.h" #include "dvb_frontend.h" -#include "mantis_vp1033.h" -#include "mantis_vp1034.h" -#include "mantis_vp1041.h" -#include "mantis_vp2033.h" -#include "mantis_vp2040.h" -#include "mantis_vp3030.h" +#include "dvb_net.h" -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +#include "mantis_common.h" +#include "mantis_dma.h" +#include "mantis_ca.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" -/* Tuner power supply control */ -void mantis_fe_powerup(struct mantis_pci *mantis) -{ - dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power ON"); - gpio_set_bits(mantis, 0x0c, 1); - msleep_interruptible(100); - gpio_set_bits(mantis, 0x0c, 1); - msleep_interruptible(100); -} +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -void mantis_fe_powerdown(struct mantis_pci *mantis) +int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power) { - dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power OFF"); - gpio_set_bits(mantis, 0x0c, 0); -} + struct mantis_hwconfig *config = mantis->hwconfig; + + switch (power) { + case POWER_ON: + dprintk(MANTIS_DEBUG, 1, "Power ON"); + gpio_set_bits(mantis, config->power, POWER_ON); + msleep(100); + gpio_set_bits(mantis, config->power, POWER_ON); + msleep(100); + break; -static int mantis_fe_reset(struct dvb_frontend *fe) -{ - struct mantis_pci *mantis = fe->dvb->priv; + case POWER_OFF: + dprintk(MANTIS_DEBUG, 1, "Power OFF"); + gpio_set_bits(mantis, config->power, POWER_OFF); + msleep(100); + break; - dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); - gpio_set_bits(mantis, 13, 0); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 0); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 1); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 1); + default: + dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power); + return -1; + } return 0; } +EXPORT_SYMBOL_GPL(mantis_frontend_power); -static int mantis_frontend_reset(struct mantis_pci *mantis) +void mantis_frontend_soft_reset(struct mantis_pci *mantis) { - dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); - gpio_set_bits(mantis, 13, 0); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 0); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 1); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 1); + struct mantis_hwconfig *config = mantis->hwconfig; + + dprintk(MANTIS_DEBUG, 1, "Frontend RESET"); + gpio_set_bits(mantis, config->reset, 0); + msleep(100); + gpio_set_bits(mantis, config->reset, 0); + msleep(100); + gpio_set_bits(mantis, config->reset, 1); + msleep(100); + gpio_set_bits(mantis, config->reset, 1); + msleep(100); + + return; +} +EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset); + +static int mantis_frontend_shutdown(struct mantis_pci *mantis) +{ + int err; + + mantis_frontend_soft_reset(mantis); + err = mantis_frontend_power(mantis, POWER_OFF); + if (err != 0) { + dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err); + return 1; + } return 0; } @@ -85,18 +106,17 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct mantis_pci *mantis = dvbdmx->priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Start feed"); + dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed"); if (!dvbdmx->dmx.frontend) { - dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); + dprintk(MANTIS_DEBUG, 1, "no frontend ?"); return -EINVAL; } + mantis->feeds++; - dprintk(verbose, MANTIS_DEBUG, 1, - "mantis start feed, feeds=%d", - mantis->feeds); + dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d", mantis->feeds); if (mantis->feeds == 1) { - dprintk(verbose, MANTIS_DEBUG, 1, "mantis start feed & dma"); + dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma"); printk("mantis start feed & dma\n"); mantis_dma_start(mantis); } @@ -109,95 +129,129 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct mantis_pci *mantis = dvbdmx->priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); + dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); if (!dvbdmx->dmx.frontend) { - dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); + dprintk(MANTIS_DEBUG, 1, "no frontend ?"); return -EINVAL; } + mantis->feeds--; if (mantis->feeds == 0) { - dprintk(verbose, MANTIS_DEBUG, 1, "mantis stop feed and dma"); + dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma"); printk("mantis stop feed and dma\n"); mantis_dma_stop(mantis); } + return 0; } int __devinit mantis_dvb_init(struct mantis_pci *mantis) { - int result; + struct mantis_hwconfig *config = mantis->hwconfig; + int result = -1; + + dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter"); + + result = dvb_register_adapter(&mantis->dvb_adapter, + "Mantis DVB adapter", + THIS_MODULE, + &mantis->pdev->dev, + adapter_nr); - dprintk(verbose, MANTIS_DEBUG, 1, "dvb_register_adapter"); - if (dvb_register_adapter(&mantis->dvb_adapter, - "Mantis dvb adapter", THIS_MODULE, - &mantis->pdev->dev, - adapter_nr) < 0) { + if (result < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Error registering adapter"); + dprintk(MANTIS_ERROR, 1, "Error registering adapter"); return -ENODEV; } - mantis->dvb_adapter.priv = mantis; - mantis->demux.dmx.capabilities = DMX_TS_FILTERING | + + mantis->dvb_adapter.priv = mantis; + mantis->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING; - mantis->demux.priv = mantis; - mantis->demux.filternum = 256; - mantis->demux.feednum = 256; - mantis->demux.start_feed = mantis_dvb_start_feed; - mantis->demux.stop_feed = mantis_dvb_stop_feed; - mantis->demux.write_to_decoder = NULL; - dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmx_init"); - if ((result = dvb_dmx_init(&mantis->demux)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, - "dvb_dmx_init failed, ERROR=%d", result); + mantis->demux.priv = mantis; + mantis->demux.filternum = 256; + mantis->demux.feednum = 256; + mantis->demux.start_feed = mantis_dvb_start_feed; + mantis->demux.stop_feed = mantis_dvb_stop_feed; + mantis->demux.write_to_decoder = NULL; + + dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init"); + result = dvb_dmx_init(&mantis->demux); + if (result < 0) { + dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); goto err0; } - mantis->dmxdev.filternum = 256; - mantis->dmxdev.demux = &mantis->demux.dmx; - mantis->dmxdev.capabilities = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmxdev_init"); - if ((result = dvb_dmxdev_init(&mantis->dmxdev, - &mantis->dvb_adapter)) < 0) { - - dprintk(verbose, MANTIS_ERROR, 1, - "dvb_dmxdev_init failed, ERROR=%d", result); + + mantis->dmxdev.filternum = 256; + mantis->dmxdev.demux = &mantis->demux.dmx; + mantis->dmxdev.capabilities = 0; + dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init"); + + result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter); + if (result < 0) { + + dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result); goto err1; } - mantis->fe_hw.source = DMX_FRONTEND_0; - if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, - &mantis->fe_hw)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, - "dvb_dmx_init failed, ERROR=%d", result); + mantis->fe_hw.source = DMX_FRONTEND_0; + result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw); + if (result < 0) { + dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); goto err2; } - mantis->fe_mem.source = DMX_MEMORY_FE; - if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, - &mantis->fe_mem)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, - "dvb_dmx_init failed, ERROR=%d", result); + mantis->fe_mem.source = DMX_MEMORY_FE; + result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx,&mantis->fe_mem); + if (result < 0) { + dprintk(MANTIS_ERROR, 1,"dvb_dmx_init failed, ERROR=%d", result); goto err3; } - if ((result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, - &mantis->fe_hw)) < 0) { - - dprintk(verbose, MANTIS_ERROR, 1, - "dvb_dmx_init failed, ERROR=%d", result); + result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw); + if (result < 0) { + dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); goto err4; } + dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); - mantis_frontend_init(mantis); - mantis_ca_init(mantis); + if (mantis->hwconfig) { + result = config->frontend_init(mantis, mantis->fe); + if (result < 0) { + dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!"); + goto err5; + } else { +// if (mantis->dvb_adapter == NULL) { +// dprintk(MANTIS_ERROR, 1, "DVB adapter "); +// goto err5; +// } + if (mantis->fe == NULL) { + dprintk(MANTIS_ERROR, 1, "FE "); + goto err5; + } + + if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) { + dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed"); + + if (mantis->fe->ops.release) + mantis->fe->ops.release(mantis->fe); + + mantis->fe = NULL; + goto err5; + } + } + } return 0; - /* Error conditions .. */ + /* Error conditions .. */ +err5: + tasklet_kill(&mantis->tasklet); + dvb_net_release(&mantis->dvbnet); err4: mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); err3: @@ -211,115 +265,17 @@ err0: return result; } +EXPORT_SYMBOL_GPL(mantis_dvb_init); -int __devinit mantis_frontend_init(struct mantis_pci *mantis) +int __devexit mantis_dvb_exit(struct mantis_pci *mantis) { - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis frontend Init"); - mantis_fe_powerup(mantis); - mantis_frontend_reset(mantis); - dprintk(verbose, MANTIS_DEBUG, 1, "Device ID=%02x", mantis->subsystem_device); - switch (mantis->subsystem_device) { - case MANTIS_VP_1033_DVB_S: // VP-1033 - dprintk(verbose, MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); - mantis->fe = stv0299_attach(&lgtdqcs001f_config, - &mantis->adapter); - - if (mantis->fe) { - mantis->fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; - dprintk(verbose, MANTIS_ERROR, 1, - "found STV0299 DVB-S frontend @ 0x%02x", - lgtdqcs001f_config.demod_address); - - dprintk(verbose, MANTIS_ERROR, 1, - "Mantis DVB-S STV0299 frontend attach success"); - } - break; - case MANTIS_VP_1034_DVB_S: // VP-1034 - dprintk(verbose, MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); - mantis->fe = mb86a16_attach(&vp1034_config, &mantis->adapter); - if (mantis->fe) { - dprintk(verbose, MANTIS_ERROR, 1, - "found MB86A16 DVB-S/DSS frontend @0x%02x", - vp1034_config.demod_address); + int err; - } - break; - case MANTIS_VP_1041_DVB_S2: - case TECHNISAT_SKYSTAR_HD2: - mantis->fe = stb0899_attach(&vp1041_config, &mantis->adapter); - if (mantis->fe) { - dprintk(verbose, MANTIS_ERROR, 1, - "found STB0899 DVB-S/DVB-S2 frontend @0x%02x", - vp1041_config.demod_address); - - if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, &mantis->adapter)) { - if (!lnbp21_attach(mantis->fe, &mantis->adapter, 0, 0)) { - printk("%s: No LNBP21 found!\n", __FUNCTION__); - mantis->fe = NULL; - } - } else { - mantis->fe = NULL; - } - } - break; - case MANTIS_VP_2033_DVB_C: // VP-2033 - case MANTIS_VP_2040_DVB_C: // VP-2040 - case TERRATEC_CINERGY_C_PCI: - case TECHNISAT_CABLESTAR_HD2: - dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - mantis->fe = tda10021_attach(&philips_cu1216_config, - &mantis->adapter, - read_pwm(mantis)); - - if (mantis->fe) { - dprintk(verbose, MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", - philips_cu1216_config.demod_address); - } else { - mantis->fe = tda10023_attach(&tda10023_cu1216_config, - &mantis->adapter, - read_pwm(mantis)); - - if (mantis->fe) { - dprintk(verbose, MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", - philips_cu1216_config.demod_address); - } - } - if (mantis->fe) { - mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; - dprintk(verbose, MANTIS_ERROR, 1, - "Mantis DVB-C Philips CU1216 frontend attach success"); - } - break; - default: - dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", - mantis->sub_device_id); + err = mantis_frontend_shutdown(mantis); + if (err != 0) + dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); - return -ENODEV; - } - if (mantis->fe == NULL) { - dprintk(verbose, MANTIS_ERROR, 1, "!!! NO Frontends found !!!"); - return -ENODEV; - } else { - if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) { - dprintk(verbose, MANTIS_ERROR, 1, - "ERROR: Frontend registration failed"); - - if (mantis->fe->ops.release) - mantis->fe->ops.release(mantis->fe); - - mantis->fe = NULL; - return -ENODEV; - } - } - - return 0; -} - -int __devexit mantis_dvb_exit(struct mantis_pci *mantis) -{ - mantis_ca_exit(mantis); +// mantis_ca_exit(mantis); tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); @@ -329,8 +285,10 @@ int __devexit mantis_dvb_exit(struct mantis_pci *mantis) if (mantis->fe) dvb_unregister_frontend(mantis->fe); - dprintk(verbose, MANTIS_DEBUG, 1, "dvb_unregister_adapter"); + + dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter"); dvb_unregister_adapter(&mantis->dvb_adapter); return 0; } +EXPORT_SYMBOL_GPL(mantis_dvb_exit); diff --git a/drivers/media/dvb/mantis/mantis_dvb.h b/drivers/media/dvb/mantis/mantis_dvb.h new file mode 100644 index 00000000000..31ebbb47df3 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dvb.h @@ -0,0 +1,15 @@ +#ifndef __MANTIS_DVB_H +#define __MANTIS_DVB_H + +enum mantis_power { + POWER_OFF = 0, + POWER_ON = 1 +}; + +extern int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power); +extern void mantis_frontend_soft_reset(struct mantis_pci *mantis); + +extern int mantis_dvb_init(struct mantis_pci *mantis); +extern int mantis_dvb_exit(struct mantis_pci *mantis); + +#endif /* __MANTIS_DVB_H */ diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 9be55f7942d..2005b2489b7 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -18,9 +18,23 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" #include "mantis_link.h" #include "mantis_hif.h" +#include "mantis_reg.h" static void mantis_hifevm_work(struct work_struct *work) { @@ -34,7 +48,7 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); mantis_event_cam_plugin(ca); dvb_ca_en50221_camchange_irq(&ca->en50221, @@ -43,7 +57,7 @@ static void mantis_hifevm_work(struct work_struct *work) } } else { if (gpif_stat & MANTIS_CARD_PLUGOUT) { - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); mantis_event_cam_unplug(ca); dvb_ca_en50221_camchange_irq(&ca->en50221, @@ -53,28 +67,28 @@ static void mantis_hifevm_work(struct work_struct *work) } if (mantis->gpif_status & MANTIS_GPIF_EXTIRQ) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); if (mantis->gpif_status & MANTIS_SBUF_WSTO) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); if (mantis->gpif_status & MANTIS_GPIF_OTHERR) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); if (gpif_stat & MANTIS_SBUF_OVFLW) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); if (gpif_stat & MANTIS_GPIF_BRRDY) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); if (gpif_stat & MANTIS_GPIF_INTSTAT) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); if (gpif_stat & MANTIS_SBUF_EMPTY) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num); if (gpif_stat & MANTIS_SBUF_OPDONE) { - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; ca->hif_event = MANTIS_SBUF_OPDONE; wake_up(&ca->hif_opdone_wq); @@ -85,7 +99,7 @@ int mantis_evmgr_init(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); + dprintk(MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); INIT_WORK(&ca->hif_evm_work, mantis_hifevm_work); mantis_pcmcia_init(ca); schedule_work(&ca->hif_evm_work); @@ -97,7 +111,7 @@ void mantis_evmgr_exit(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); + dprintk(MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); flush_scheduled_work(); mantis_hif_exit(ca); mantis_pcmcia_exit(ca); diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 99a9724cbaf..bb05427fdeb 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -18,10 +18,28 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" + #include "mantis_hif.h" #include "mantis_link.h" /* temporary due to physical layer stuff */ +#include "mantis_reg.h" + static int mantis_hif_data_available(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; @@ -31,7 +49,7 @@ static int mantis_hif_data_available(struct mantis_ca *ca) ca->sbuf_status & MANTIS_SBUF_DATA_AVAIL, msecs_to_jiffies(500)) == -ERESTARTSYS) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Read wait event timeout !", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Read wait event timeout !", mantis->num); rc = -EREMOTEIO; } ca->sbuf_status &= ~MANTIS_SBUF_DATA_AVAIL; @@ -48,10 +66,10 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) ca->hif_event & MANTIS_SBUF_OPDONE, msecs_to_jiffies(500)) == -ERESTARTSYS) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num); rc = -EREMOTEIO; } - dprintk(verbose, MANTIS_DEBUG, 1, "Smart Buffer Operation complete"); + dprintk(MANTIS_DEBUG, 1, "Smart Buffer Operation complete"); ca->hif_event &= ~MANTIS_SBUF_OPDONE; return rc; } @@ -66,22 +84,22 @@ static int mantis_hif_write_wait(struct mantis_ca *ca) mantis->gpif_status & MANTIS_GPIF_WRACK, msecs_to_jiffies(500)) == -ERESTARTSYS) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed out !", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed out !", mantis->num); rc = -EREMOTEIO; } - dprintk(verbose, MANTIS_DEBUG, 1, "Write Acknowledged"); + dprintk(MANTIS_DEBUG, 1, "Write Acknowledged"); mantis->gpif_status &= ~MANTIS_GPIF_WRACK; while (!opdone) { opdone = (mmread(MANTIS_GPIF_STATUS) & MANTIS_SBUF_OPDONE); udelay(500); timeout++; if (timeout > 100) { - dprintk(verbose, MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num); rc = -ETIMEDOUT; break; } } - dprintk(verbose, MANTIS_DEBUG, 1, "HIF Write success"); + dprintk(MANTIS_DEBUG, 1, "HIF Write success"); return rc; } @@ -91,7 +109,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0, data, count = 4; - dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num); mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; @@ -104,13 +122,13 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); if (mantis_hif_sbuf_opdone_wait(ca) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } data = mmread(MANTIS_GPIF_DIN); mutex_unlock(&ca->ca_lock); - dprintk(verbose, MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data); + dprintk(MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data); return (data >> 24) & 0xff; } @@ -120,7 +138,7 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num); mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; @@ -133,11 +151,11 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(data, MANTIS_GPIF_DOUT); if (mantis_hif_write_wait(ca) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } - dprintk(verbose, MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr); + dprintk(MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr); mutex_unlock(&ca->ca_lock); return 0; @@ -148,7 +166,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) struct mantis_pci *mantis = ca->ca_priv; u32 data, hif_addr = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num); mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr |= MANTIS_GPIF_PCMCIAIOM; @@ -161,12 +179,12 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); if (mantis_hif_sbuf_opdone_wait(ca) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } data = mmread(MANTIS_GPIF_DIN); - dprintk(verbose, MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); + dprintk(MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); udelay(50); mutex_unlock(&ca->ca_lock); @@ -178,7 +196,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num); mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_HIFRDWRN; @@ -190,11 +208,11 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(data, MANTIS_GPIF_DOUT); if (mantis_hif_write_wait(ca) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } - dprintk(verbose, MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); + dprintk(MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); mutex_unlock(&ca->ca_lock); udelay(50); @@ -208,7 +226,7 @@ int mantis_hif_init(struct mantis_ca *ca) u32 irqcfg; slot[0].slave_cfg = 0x70773028; - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); mutex_lock(&ca->ca_lock); irqcfg = mmread(MANTIS_GPIF_IRQCFG); @@ -230,7 +248,7 @@ void mantis_hif_exit(struct mantis_ca *ca) struct mantis_pci *mantis = ca->ca_priv; u32 irqcfg; - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num); mutex_lock(&ca->ca_lock); irqcfg = mmread(MANTIS_GPIF_IRQCFG); irqcfg &= ~MANTIS_MASK_BRRDY; diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/dvb/mantis/mantis_hif.h index 7ef45cec19d..f960c0aeacc 100644 --- a/drivers/media/dvb/mantis/mantis_hif.h +++ b/drivers/media/dvb/mantis/mantis_hif.h @@ -26,4 +26,4 @@ #define MANTIS_HIF_IOMRD 3 #define MANTIS_HIF_IOMWR 4 -#endif // __MANTIS_HIF_H +#endif /* __MANTIS_HIF_H */ diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 45d9e6bd962..ba55f0a9a10 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -18,15 +18,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include -#include -#include #include #include -#include -#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_i2c.h" #define I2C_HW_B_MANTIS 0x1c @@ -35,20 +40,21 @@ static int mantis_ack_wait(struct mantis_pci *mantis) int rc = 0; u32 timeout = 0; - if (wait_event_interruptible_timeout(mantis->i2c_wq, - mantis->mantis_int_stat & MANTIS_INT_I2CDONE, - msecs_to_jiffies(50)) == -ERESTARTSYS) { + if (wait_event_timeout(mantis->i2c_wq, + mantis->mantis_int_stat & MANTIS_INT_I2CDONE, + msecs_to_jiffies(50)) == -ERESTARTSYS) { - dprintk(verbose, MANTIS_DEBUG, 1, "Master !I2CDONE"); + dprintk(MANTIS_DEBUG, 1, "Master !I2CDONE"); rc = -EREMOTEIO; } + while (!(mantis->mantis_int_stat & MANTIS_INT_I2CRACK)) { - dprintk(verbose, MANTIS_DEBUG, 1, "Waiting for Slave RACK"); + dprintk(MANTIS_DEBUG, 1, "Waiting for Slave RACK"); mantis->mantis_int_stat = mmread(MANTIS_INT_STAT); msleep(5); timeout++; if (timeout > 500) { - dprintk(verbose, MANTIS_ERROR, 1, "Slave RACK Fail !"); + dprintk(MANTIS_ERROR, 1, "Slave RACK Fail !"); rc = -EREMOTEIO; break; } @@ -62,7 +68,7 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) { u32 rxd, i; - dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", + dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); for (i = 0; i < msg->len; i++) { @@ -77,14 +83,14 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(rxd, MANTIS_I2CDATA_CTL); if (mantis_ack_wait(mantis) != 0) { - dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); + dprintk(MANTIS_DEBUG, 1, "ACK failed"); return -EREMOTEIO; } rxd = mmread(MANTIS_I2CDATA_CTL); msg->buf[i] = (u8)((rxd >> 8) & 0xFF); - dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); + dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]); } - dprintk(verbose, MANTIS_INFO, 0, "]\n"); + dprintk(MANTIS_INFO, 0, "]\n"); return 0; } @@ -94,11 +100,11 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg int i; u32 txd = 0; - dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", + dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); for (i = 0; i < msg->len; i++) { - dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); + dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]); txd = (msg->addr << 25) | (msg->buf[i] << 8) | MANTIS_I2C_RATE_3 | MANTIS_I2C_STOP @@ -110,11 +116,11 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(txd, MANTIS_I2CDATA_CTL); if (mantis_ack_wait(mantis) != 0) { - dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); + dprintk(MANTIS_DEBUG, 1, "ACK failed"); return -EREMOTEIO; } } - dprintk(verbose, MANTIS_INFO, 0, "]\n"); + dprintk(MANTIS_INFO, 0, "]\n"); return 0; } @@ -154,43 +160,46 @@ static struct i2c_algorithm mantis_algo = { .functionality = mantis_i2c_func, }; -static struct i2c_adapter mantis_i2c_adapter = { - .owner = THIS_MODULE, - .name = "Mantis I2C", - .id = I2C_HW_B_MANTIS, - .class = I2C_CLASS_TV_DIGITAL, - .algo = &mantis_algo, -}; - int __devinit mantis_i2c_init(struct mantis_pci *mantis) { u32 intstat, intmask; struct i2c_adapter *i2c_adapter = &mantis->adapter; struct pci_dev *pdev = mantis->pdev; + init_waitqueue_head(&mantis->i2c_wq); mutex_init(&mantis->i2c_lock); - memcpy(i2c_adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); + strncpy(i2c_adapter->name, "Mantis I2C", sizeof (i2c_adapter->name)); i2c_set_adapdata(i2c_adapter, mantis); - i2c_adapter->dev.parent = &pdev->dev; + i2c_adapter->owner = THIS_MODULE; + i2c_adapter->class = I2C_CLASS_TV_DIGITAL; + i2c_adapter->algo = &mantis_algo; + i2c_adapter->algo_data = NULL; + i2c_adapter->id = I2C_HW_B_MANTIS; + i2c_adapter->timeout = 500; + i2c_adapter->retries = 3; + i2c_adapter->dev.parent = &pdev->dev; + mantis->i2c_rc = i2c_add_adapter(i2c_adapter); if (mantis->i2c_rc < 0) return mantis->i2c_rc; - dprintk(verbose, MANTIS_DEBUG, 1, "Initializing I2C .."); + dprintk(MANTIS_DEBUG, 1, "Initializing I2C .."); intstat = mmread(MANTIS_INT_STAT); intmask = mmread(MANTIS_INT_MASK); mmwrite(intstat, MANTIS_INT_STAT); mmwrite(intmask | MANTIS_INT_I2CDONE, MANTIS_INT_MASK); - dprintk(verbose, MANTIS_DEBUG, 1, "[0x%08x/%08x]", intstat, intmask); + dprintk(MANTIS_DEBUG, 1, "Status=<%02x> Mask=<%02x>", intstat, intmask); return 0; } +EXPORT_SYMBOL_GPL(mantis_i2c_init); int __devexit mantis_i2c_exit(struct mantis_pci *mantis) { - dprintk(verbose, MANTIS_DEBUG, 1, "Removing I2C adapter"); + dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter"); return i2c_del_adapter(&mantis->adapter); } +EXPORT_SYMBOL_GPL(mantis_i2c_exit); diff --git a/drivers/media/dvb/mantis/mantis_i2c.h b/drivers/media/dvb/mantis/mantis_i2c.h new file mode 100644 index 00000000000..1e49ecfeee3 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_i2c.h @@ -0,0 +1,7 @@ +#ifndef __MANTIS_I2C_H +#define __MANTIS_I2C_H + +extern int mantis_i2c_init(struct mantis_pci *mantis); +extern int mantis_i2c_exit(struct mantis_pci *mantis); + +#endif /* __MANTIS_I2C_H */ diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c new file mode 100644 index 00000000000..4700088f038 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ioc.c @@ -0,0 +1,145 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_ioc.h" + +static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + int err; + struct i2c_msg msg[] = { + { .addr = 0x50, .flags = 0, .buf = data, .len = 1 }, + { .addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = length }, + }; + + err = i2c_transfer(adapter, msg, 2); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >", + err, data[0], data[1]); + + return err; + } + + return 0; +} + +static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +{ + struct i2c_adapter *adapter = &mantis->adapter; + int err; + + struct i2c_msg msg = { .addr = 0x50, .flags = 0, .buf = data, .len = length }; + + err = i2c_transfer(adapter, &msg, 1); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", + err, length, data[0], data[1]); + + return err; + } + + return 0; +} + +int mantis_get_mac(struct mantis_pci *mantis) +{ + int err; + + mantis->mac_address[0] = 0x08; + + err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis EEPROM read error <%d>", err); + + return err; + } + + dprintk(MANTIS_ERROR, 0, + " MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n", + mantis->mac_address[0], mantis->mac_address[1], + mantis->mac_address[2], mantis->mac_address[3], + mantis->mac_address[4], mantis->mac_address[5]); + + return 0; +} +EXPORT_SYMBOL_GPL(mantis_get_mac); + +/* Turn the given bit on or off. */ +void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) +{ + u32 cur; + + cur = mmread(MANTIS_GPIF_ADDR); + if (value) + mantis->gpio_status = cur | (1 << bitpos); + else + mantis->gpio_status = cur & (~(1 << bitpos)); + + mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR); + mmwrite(0x00, MANTIS_GPIF_DOUT); +} +EXPORT_SYMBOL_GPL(gpio_set_bits); + +int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl) +{ + u32 reg; + + reg = mmread(MANTIS_CONTROL); + switch (stream_ctl) { + case STREAM_TO_HIF: + dprintk(MANTIS_DEBUG, 1, "Set stream to HIF"); + reg &= 0xff - MANTIS_BYPASS; + mmwrite(reg, MANTIS_CONTROL); + reg |= MANTIS_BYPASS; + mmwrite(reg, MANTIS_CONTROL); + break; + + case STREAM_TO_CAM: + dprintk(MANTIS_DEBUG, 1, "Set stream to CAM"); + reg |= MANTIS_BYPASS; + mmwrite(reg, MANTIS_CONTROL); + reg &= 0xff - MANTIS_BYPASS; + mmwrite(reg, MANTIS_CONTROL); + break; + default: + dprintk(MANTIS_ERROR, 1, "Unknown MODE <%02x>", stream_ctl); + return -1; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mantis_stream_control); diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index f9aaaa52f52..f6030c9fba2 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -58,7 +58,6 @@ struct mantis_ca { enum mantis_slot_state slot_state; -// struct dvb_device *ca_dev; void *ca_priv; struct dvb_ca_en50221 en50221; @@ -81,4 +80,4 @@ extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data); extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr); extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data); -#endif // __MANTIS_LINK_H +#endif /* __MANTIS_LINK_H */ diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index d1eac4083fc..5165a390e07 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -18,6 +18,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include #include #include #include @@ -25,264 +28,149 @@ #include #include #include -#include "mantis_common.h" -#include "mantis_core.h" -#include "mantis_uart.h" +#include #include #include #include #include -unsigned int verbose = 1; -module_param(verbose, int, 0644); -MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); - -unsigned int devs; - -#define PCI_VENDOR_ID_MANTIS 0x1822 -#define PCI_DEVICE_ID_MANTIS_R11 0x4e35 -#define DRIVER_NAME "Mantis" - -static struct pci_device_id mantis_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_MANTIS, PCI_DEVICE_ID_MANTIS_R11) }, - { 0 }, -}; - -MODULE_DEVICE_TABLE(pci, mantis_pci_table); - -static irqreturn_t mantis_pci_irq(int irq, void *dev_id) -{ - u32 stat = 0, mask = 0, lstat = 0, mstat = 0; - u32 rst_stat = 0, rst_mask = 0; +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" - struct mantis_pci *mantis; - struct mantis_ca *ca; +#include +#include +#include +#include - mantis = (struct mantis_pci *) dev_id; - if (unlikely(mantis == NULL)) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis == NULL"); - return IRQ_NONE; - } - ca = mantis->mantis_ca; - - stat = mmread(MANTIS_INT_STAT); - mask = mmread(MANTIS_INT_MASK); - mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; - if (!(stat & mask)) - return IRQ_NONE; - - rst_mask = MANTIS_GPIF_WRACK | - MANTIS_GPIF_OTHERR | - MANTIS_SBUF_WSTO | - MANTIS_GPIF_EXTIRQ; - - rst_stat = mmread(MANTIS_GPIF_STATUS); - rst_stat &= rst_mask; - mmwrite(rst_stat, MANTIS_GPIF_STATUS); - - mantis->mantis_int_stat = stat; - mantis->mantis_int_mask = mask; - dprintk(verbose, MANTIS_DEBUG, 0, "=== Interrupts[%04x/%04x]= [", stat, mask); - if (stat & MANTIS_INT_RISCEN) { - dprintk(verbose, MANTIS_DEBUG, 0, "* DMA enabl *"); - } - if (stat & MANTIS_INT_IRQ0) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); - mantis->gpif_status = rst_stat; - wake_up(&ca->hif_write_wq); - schedule_work(&ca->hif_evm_work); - } - if (stat & MANTIS_INT_IRQ1) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); - schedule_work(&mantis->uart_work); - } - if (stat & MANTIS_INT_OCERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT OCERR *"); - } - if (stat & MANTIS_INT_PABORT) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT PABRT *"); - } - if (stat & MANTIS_INT_RIPERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT RIPRR *"); - } - if (stat & MANTIS_INT_PPERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT PPERR *"); - } - if (stat & MANTIS_INT_FTRGT) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT FTRGT *"); - } - if (stat & MANTIS_INT_RISCI) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT RISCI *"); - mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; - tasklet_schedule(&mantis->tasklet); - } - if (stat & MANTIS_INT_I2CDONE) { - dprintk(verbose, MANTIS_DEBUG, 0, "* I2C DONE *"); - wake_up(&mantis->i2c_wq); - } - mmwrite(stat, MANTIS_INT_STAT); - stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | - MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | - MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | - MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | - MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | - MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | - MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | - MANTIS_INT_PABORT | MANTIS_INT_RIPERR | - MANTIS_INT_PPERR | MANTIS_INT_FTRGT | - MANTIS_INT_RISCI); - - if (stat) - dprintk(verbose, MANTIS_DEBUG, 0, "* Unknown [%04x] *", stat); - - dprintk(verbose, MANTIS_DEBUG, 0, "] ===\n"); - - return IRQ_HANDLED; -} +#include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_pci.h" +#define DRIVER_NAME "Mantis Core" -static int __devinit mantis_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *mantis_pci_table) +int __devinit mantis_pci_init(struct mantis_pci *mantis) { u8 revision, latency; - struct mantis_pci *mantis; - int ret = 0; + struct mantis_hwconfig *config = mantis->hwconfig; + struct pci_dev *pdev = mantis->pdev; + int err, ret = 0; + + dprintk(MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n", + config->model_name, + config->dev_type, + mantis->pdev->bus->number, + PCI_SLOT(mantis->pdev->devfn), + PCI_FUNC(mantis->pdev->devfn)); + + err = pci_enable_device(pdev); + if (err != 0) { + ret = -ENODEV; + dprintk(MANTIS_ERROR, 1, "ERROR: PCI enable failed <%i>", err); + goto fail0; + } - mantis = kmalloc(sizeof (struct mantis_pci), GFP_KERNEL); - if (mantis == NULL) { - printk("%s: Out of memory\n", __func__); + err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (err != 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Unable to obtain 32 bit DMA <%i>", err); ret = -ENOMEM; - goto err; + goto fail1; } - memset(mantis, 0, sizeof (struct mantis_pci)); - mantis->num = devs; - devs++; - if (pci_enable_device(pdev)) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis PCI enable failed"); - ret = -ENODEV; - goto err; - } - mantis->mantis_addr = pci_resource_start(pdev, 0); - if (!request_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0), DRIVER_NAME)) { - ret = -ENODEV; - goto err0; - } + pci_set_master(pdev); - mantis->mantis_mmio = ioremap(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + if (!request_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0), + DRIVER_NAME)) { - if (!mantis->mantis_mmio) { - dprintk(verbose, MANTIS_ERROR, 1, "IO remap failed"); + dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 Request failed !"); ret = -ENODEV; - goto err1; + goto fail1; } - // Clear and disable all interrupts at startup - // to avoid lockup situations - mmwrite(0x00, MANTIS_INT_MASK); - if (request_irq(pdev->irq, - mantis_pci_irq, - IRQF_SHARED, - DRIVER_NAME, - mantis) < 0) { + mantis->mmio = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); - dprintk(verbose, MANTIS_ERROR, 1, "Mantis IRQ reg failed"); + if (!mantis->mmio) { + dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 remap failed !"); ret = -ENODEV; - goto err2; + goto fail2; } - pci_set_master(pdev); - pci_set_drvdata(pdev, mantis); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); mantis->latency = latency; mantis->revision = revision; - mantis->pdev = pdev; - mantis->subsystem_vendor = pdev->subsystem_vendor; - mantis->subsystem_device = pdev->subsystem_device; - init_waitqueue_head(&mantis->i2c_wq); - mantis_set_direction(mantis, 0); /* CAM bypass */ + dprintk(MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", + mantis->revision, + mantis->pdev->subsystem_vendor, + mantis->pdev->subsystem_device); + + dprintk(MANTIS_ERROR, 0, + "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", + mantis->pdev->irq, + mantis->latency, + mantis->mantis_addr, + mantis->mmio); - if (!latency) - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 32); + err = request_irq(pdev->irq, + config->irq_handler, + IRQF_SHARED, + DRIVER_NAME, + mantis); - dprintk(verbose, MANTIS_ERROR, 0, - "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", - pdev->irq, mantis->latency, - mantis->mantis_addr, mantis->mantis_mmio); + if (err != 0) { - // No more PCI specific stuff ! - if (mantis_core_init(mantis) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis core init failed"); + dprintk(MANTIS_ERROR, 1, "ERROR: IRQ registration failed ! <%d>", err); ret = -ENODEV; - goto err2; + goto fail3; } - return 0; + pci_set_drvdata(pdev, mantis); + return ret; - // Error conditions .. -err2: - dprintk(verbose, MANTIS_DEBUG, 1, "Err: IO Unmap"); - if (mantis->mantis_mmio) - iounmap(mantis->mantis_mmio); -err1: - dprintk(verbose, MANTIS_DEBUG, 1, "Err: Release regions"); + /* Error conditions */ +fail3: + dprintk(MANTIS_ERROR, 1, "ERROR: <%d> I/O unmap", ret); + if (mantis->mmio) + iounmap(mantis->mmio); + +fail2: + dprintk(MANTIS_ERROR, 1, "ERROR: <%d> releasing regions", ret); release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + pci_resource_len(pdev, 0)); + +fail1: + dprintk(MANTIS_ERROR, 1, "ERROR: <%d> disabling device", ret); pci_disable_device(pdev); -err0: - dprintk(verbose, MANTIS_DEBUG, 1, "Err: Free"); - kfree(mantis); -err: - dprintk(verbose, MANTIS_DEBUG, 1, "Err:"); + +fail0: + dprintk(MANTIS_ERROR, 1, "ERROR: <%d> exiting", ret); + pci_set_drvdata(pdev, NULL); return ret; } +EXPORT_SYMBOL_GPL(mantis_pci_init); -static void __devexit mantis_pci_remove(struct pci_dev *pdev) +void __devexit mantis_pci_exit(struct mantis_pci *mantis) { - struct mantis_pci *mantis = pci_get_drvdata(pdev); - - if (mantis == NULL) { - dprintk(verbose, MANTIS_ERROR, 1, "Aeio, Mantis NULL ptr"); - return; - } - mantis_core_exit(mantis); - dprintk(verbose, MANTIS_ERROR, 1, "Removing -->Mantis irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p", - pdev->irq, mantis->latency, mantis->mantis_addr, - mantis->mantis_mmio); + struct pci_dev *pdev = mantis->pdev; + dprintk(MANTIS_NOTICE, 1, " mem: 0x%p", mantis->mmio); free_irq(pdev->irq, mantis); - pci_release_regions(pdev); - if (mantis_dma_exit(mantis) < 0) - dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); + if (mantis->mmio) { + iounmap(mantis->mmio); + release_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + } - pci_set_drvdata(pdev, NULL); pci_disable_device(pdev); - kfree(mantis); -} - -static struct pci_driver mantis_pci_driver = { - .name = DRIVER_NAME, - .id_table = mantis_pci_table, - .probe = mantis_pci_probe, - .remove = mantis_pci_remove, -}; - -static int __devinit mantis_pci_init(void) -{ - return pci_register_driver(&mantis_pci_driver); -} - -static void __devexit mantis_pci_exit(void) -{ - pci_unregister_driver(&mantis_pci_driver); + pci_set_drvdata(pdev, NULL); } - -module_init(mantis_pci_init); -module_exit(mantis_pci_exit); +EXPORT_SYMBOL_GPL(mantis_pci_exit); MODULE_DESCRIPTION("Mantis PCI DTV bridge driver"); MODULE_AUTHOR("Manu Abraham"); diff --git a/drivers/media/dvb/mantis/mantis_pci.h b/drivers/media/dvb/mantis/mantis_pci.h new file mode 100644 index 00000000000..5ce776ffcb3 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_pci.h @@ -0,0 +1,7 @@ +#ifndef __MANTIS_PCI_H +#define __MANTIS_PCI_H + +extern int mantis_pci_init(struct mantis_pci *mantis); +extern void mantis_pci_exit(struct mantis_pci *mantis); + +#endif /* __MANTIS_PCI_H */ diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 4156a082088..90ca356985e 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -18,8 +18,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" #include "mantis_link.h" /* temporary due to physical layer stuff */ +#include "mantis_reg.h" /* * If Slot state is already PLUG_IN event and we are called @@ -32,7 +46,7 @@ void mantis_event_cam_plugin(struct mantis_ca *ca) u32 gpif_irqcfg; if (ca->slot_state == MODULE_XTRACTED) { - dprintk(verbose, MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num); udelay(50); mmwrite(0xda000000, MANTIS_CARD_RESET); gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); @@ -56,7 +70,7 @@ void mantis_event_cam_unplug(struct mantis_ca *ca) u32 gpif_irqcfg; if (ca->slot_state == MODULE_INSERTED) { - dprintk(verbose, MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num); udelay(50); mmwrite(0x00da0000, MANTIS_CARD_RESET); gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); @@ -80,14 +94,14 @@ int mantis_pcmcia_init(struct mantis_ca *ca) card_stat = mmread(MANTIS_GPIF_IRQCFG); if (gpif_stat & MANTIS_GPIF_DETSTAT) { - dprintk(verbose, MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); + dprintk(MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_INSERTED; dvb_ca_en50221_camchange_irq(&ca->en50221, 0, DVB_CA_EN50221_CAMCHANGE_INSERTED); } else { - dprintk(verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_XTRACTED; dvb_ca_en50221_camchange_irq(&ca->en50221, diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h index 6f5cd493676..0072e149a56 100644 --- a/drivers/media/dvb/mantis/mantis_reg.h +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -21,7 +21,7 @@ #ifndef __MANTIS_REG_H #define __MANTIS_REG_H -// Interrupts +/* Interrupts */ #define MANTIS_INT_STAT 0x00 #define MANTIS_INT_MASK 0x04 @@ -49,8 +49,12 @@ #define MANTIS_INT_RISCI (0x01 << 1) #define MANTIS_INT_I2CDONE (0x01 << 0) -// DMA +/* DMA */ #define MANTIS_DMA_CTL 0x08 +#define MANTIS_GPIF_RD (0xff << 24) +#define MANTIS_GPIF_WR (0xff << 16) +#define MANTIS_CPU_DO (0x01 << 10) +#define MANTIS_DRV_DO (0x01 << 9) #define MANTIS_I2C_RD (0x01 << 7) #define MANTIS_I2C_WR (0x01 << 6) #define MANTIS_DCAP_MODE (0x01 << 5) @@ -61,10 +65,16 @@ #define MANTIS_DCAP_EN (0x01 << 1) #define MANTIS_RISC_EN (0x01 << 0) +/* DEBUG */ +#define MANTIS_DEBUGREG 0x0c +#define MANTIS_DATINV (0x0e << 7) +#define MANTIS_TOP_DEBUGSEL (0x07 << 4) +#define MANTIS_PCMCIA_DEBUGSEL (0x0f << 0) + #define MANTIS_RISC_START 0x10 #define MANTIS_RISC_PC 0x14 -// I2C +/* I2C */ #define MANTIS_I2CDATA_CTL 0x18 #define MANTIS_I2C_RATE_1 (0x00 << 6) #define MANTIS_I2C_RATE_2 (0x01 << 6) @@ -73,6 +83,28 @@ #define MANTIS_I2C_STOP (0x01 << 5) #define MANTIS_I2C_PGMODE (0x01 << 3) +/* DATA */ +#define MANTIS_CMD_DATA_R1 0x20 +#define MANTIS_CMD_DATA_3 (0xff << 24) +#define MANTIS_CMD_DATA_2 (0xff << 16) +#define MANTIS_CMD_DATA_1 (0xff << 8) +#define MANTIS_CMD_DATA_0 (0xff << 0) + +#define MANTIS_CMD_DATA_R2 0x24 +#define MANTIS_CMD_DATA_7 (0xff << 24) +#define MANTIS_CMD_DATA_6 (0xff << 16) +#define MANTIS_CMD_DATA_5 (0xff << 8) +#define MANTIS_CMD_DATA_4 (0xff << 0) + +#define MANTIS_CONTROL 0x28 +#define MANTIS_DET (0x01 << 7) +#define MANTIS_DAT_CF_EN (0x01 << 6) +#define MANTIS_ACS (0x03 << 4) +#define MANTIS_VCCEN (0x01 << 3) +#define MANTIS_BYPASS (0x01 << 2) +#define MANTIS_MRST (0x01 << 1) +#define MANTIS_CRST_INT (0x01 << 0) + #define MANTIS_GPIF_CFGSLA 0x84 #define MANTIS_GPIF_WAITSMPL (0x07 << 28) #define MANTIS_GPIF_BYTEADDRSUB (0x01 << 25) @@ -162,4 +194,4 @@ #define MANTIS_GPIF_LOGICRD (0xffff << 16) #define MANTIS_GPIF_LOGICRW (0xffff << 0) -#endif //__MANTIS_REG_H +#endif /* __MANTIS_REG_H */ diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c index 786fcc33911..fb423b0a58f 100644 --- a/drivers/media/dvb/mantis/mantis_uart.c +++ b/drivers/media/dvb/mantis/mantis_uart.c @@ -1,5 +1,20 @@ +#include #include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_uart.h" struct mantis_uart_params { enum mantis_baud baud_rate; @@ -18,20 +33,20 @@ int mantis_uart_read(struct mantis_pci *mantis, u8 *data) for (i = 0; i < (config->bytes + 1); i++) { if (stat & MANTIS_UART_RXFIFO_FULL) { - dprintk(verbose, MANTIS_ERROR, 1, "RX Fifo FULL"); + dprintk(MANTIS_ERROR, 1, "RX Fifo FULL"); } data[i] = mmread(MANTIS_UART_RXD) & 0x3f; stat = mmread(MANTIS_UART_STAT); - dprintk(verbose, MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f); + dprintk(MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f); if (data[i] & (1 << 7)) { - dprintk(verbose, MANTIS_ERROR, 1, "UART framing error"); + dprintk(MANTIS_ERROR, 1, "UART framing error"); return -EINVAL; } if (data[i] & (1 << 6)) { - dprintk(verbose, MANTIS_ERROR, 1, "UART parity error"); + dprintk(MANTIS_ERROR, 1, "UART parity error"); return -EINVAL; } } @@ -46,14 +61,14 @@ static void mantis_uart_work(struct work_struct *work) u8 buf[16]; int i; - dprintk(verbose, MANTIS_DEBUG, 1, "UART read"); + dprintk(MANTIS_DEBUG, 1, "UART read"); mantis_uart_read(mantis, buf); - dprintk(verbose, MANTIS_DEBUG, 1, "UART: "); + dprintk(MANTIS_DEBUG, 1, "UART: "); for (i = 0; i < (config->bytes + 1); i++) - dprintk(verbose, MANTIS_DEBUG, 0, "<%02x> ", buf[i]); + dprintk(MANTIS_DEBUG, 0, "<%02x> ", buf[i]); - dprintk(verbose, MANTIS_DEBUG, 0, "\n"); + dprintk(MANTIS_DEBUG, 0, "\n"); } static int mantis_uart_setup(struct mantis_pci *mantis, @@ -64,7 +79,7 @@ static int mantis_uart_setup(struct mantis_pci *mantis, u32 reg; - dprintk(verbose, MANTIS_DEBUG, 1, "Set Parity <%s> Baud Rate <%s>", + dprintk(MANTIS_DEBUG, 1, "Set Parity <%s> Baud Rate <%s>", parity[params->parity], rates[params->baud_rate]); @@ -102,7 +117,7 @@ int mantis_uart_init(struct mantis_pci *mantis) struct mantis_hwconfig *config = mantis->hwconfig; struct mantis_uart_params params; - dprintk(verbose, MANTIS_DEBUG, 1, "Initializing UART .."); + dprintk(MANTIS_DEBUG, 1, "Initializing UART .."); /* default parity: */ params.baud_rate = config->baud_rate; params.parity = config->parity; @@ -131,9 +146,11 @@ int mantis_uart_init(struct mantis_pci *mantis) return 0; } +EXPORT_SYMBOL_GPL(mantis_uart_init); void mantis_uart_exit(struct mantis_pci *mantis) { /* disable interrupt */ mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL); } +EXPORT_SYMBOL_GPL(mantis_uart_exit); diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h index e9f938d37c3..0a42cd01ab2 100644 --- a/drivers/media/dvb/mantis/mantis_uart.h +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -56,4 +56,4 @@ struct mantis_pci; extern int mantis_uart_init(struct mantis_pci *mantis); extern void mantis_uart_exit(struct mantis_pci *mantis); -#endif // __MANTIS_UART_H +#endif /* __MANTIS_UART_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 64cdfb8b709..f2092ce9c4b 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -18,6 +18,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "stv0299.h" #include "mantis_common.h" #include "mantis_vp1033.h" @@ -66,47 +78,21 @@ u8 lgtdqcs001f_inittab[] = { 0xff, 0xff, }; -struct stv0299_config lgtdqcs001f_config = { - .demod_address = 0x68, - .inittab = lgtdqcs001f_inittab, - .mclk = 88000000UL, -// .invert = 0, - .invert = 1, -// .enhanced_tuning = 0, - .skip_reinit = 0, -// .lock_output = STV0229_LOCKOUTPUT_0, - .volt13_op0_op1 = STV0299_VOLT13_OP0, - .min_delay_ms = 100, - .set_symbol_rate = lgtdqcs001f_set_symbol_rate, -// .pll_set = lgtdqcs001f_pll_set, -}; - #define MANTIS_MODEL_NAME "VP-1033" #define MANTIS_DEV_TYPE "DVB-S/DSS" -struct mantis_hwconfig vp1033_mantis_config = { - .model_name = MANTIS_MODEL_NAME, - .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_204, - .baud_rate = MANTIS_BAUD_9600, - .parity = MANTIS_PARITY_NONE, - .bytes = 0, -}; - int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { + struct mantis_pci *mantis = fe->dvb->priv; + struct i2c_adapter *adapter = &mantis->adapter; + u8 buf[4]; u32 div; - struct mantis_pci *mantis = fe->dvb->priv; - struct i2c_msg msg = { - .addr = 0x61, - .flags = 0, - .buf = buf, - .len = sizeof (buf) - }; + struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof (buf) }; + div = params->frequency / 250; buf[0] = (div >> 8) & 0x7f; @@ -118,8 +104,8 @@ int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, buf[3] |= 0x04; else buf[3] &= ~0x04; - if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Write: I2C Transfer failed"); + if (i2c_transfer(adapter, &msg, 1) < 0) { + dprintk(MANTIS_ERROR, 1, "Write: I2C Transfer failed"); return -EIO; } msleep_interruptible(100); @@ -161,3 +147,49 @@ int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, return 0; } + +struct stv0299_config lgtdqcs001f_config = { + .demod_address = 0x68, + .inittab = lgtdqcs001f_inittab, + .mclk = 88000000UL, + .invert = 0, + .skip_reinit = 0, + .volt13_op0_op1 = STV0299_VOLT13_OP0, + .min_delay_ms = 100, + .set_symbol_rate = lgtdqcs001f_set_symbol_rate, +}; + +static int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); + fe = stv0299_attach(&lgtdqcs001f_config, adapter); + + if (fe) { + fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; + dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x", + lgtdqcs001f_config.demod_address); + + dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success"); + } else { + return -1; + } + + mantis->fe = fe; + dprintk(MANTIS_ERROR, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp1033_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp1033_frontend_init, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/dvb/mantis/mantis_vp1033.h index e24570659d5..2c18d215324 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.h +++ b/drivers/media/dvb/mantis/mantis_vp1033.h @@ -21,19 +21,10 @@ #ifndef __MANTIS_VP1033_H #define __MANTIS_VP1033_H -#include "dvb_frontend.h" #include "mantis_common.h" -#include "stv0299.h" #define MANTIS_VP_1033_DVB_S 0x0016 -extern struct stv0299_config lgtdqcs001f_config; -extern struct mantis_hwconfig vp1033_mantis_config; +extern struct mantis_hwconfig vp1033_config; -extern int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params); - -extern int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio); - - -#endif // __MANTIS_VP1033_H +#endif /* __MANTIS_VP1033_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 28f3420b231..40778ec8f46 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -18,10 +18,24 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "mb86a16.h" #include "mantis_common.h" +#include "mantis_ioc.h" #include "mantis_vp1034.h" +#include "mantis_reg.h" -struct mb86a16_config vp1034_config = { +struct mb86a16_config vp1034_mb86a16_config = { .demod_address = 0x08, .set_voltage = vp1034_set_voltage, }; @@ -29,38 +43,62 @@ struct mb86a16_config vp1034_config = { #define MANTIS_MODEL_NAME "VP-1034" #define MANTIS_DEV_TYPE "DVB-S/DSS" -struct mantis_hwconfig vp1034_mantis_config = { - .model_name = MANTIS_MODEL_NAME, - .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_204, - .baud_rate = MANTIS_BAUD_9600, - .parity = MANTIS_PARITY_NONE, - .bytes = 0, -}; - int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct mantis_pci *mantis = fe->dvb->priv; switch (voltage) { case SEC_VOLTAGE_13: - dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[13V]"); + dprintk(MANTIS_ERROR, 1, "Polarization=[13V]"); gpio_set_bits(mantis, 13, 1); gpio_set_bits(mantis, 14, 0); break; case SEC_VOLTAGE_18: - dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[18V]"); + dprintk(MANTIS_ERROR, 1, "Polarization=[18V]"); gpio_set_bits(mantis, 13, 1); gpio_set_bits(mantis, 14, 1); break; case SEC_VOLTAGE_OFF: - dprintk(verbose, MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); + dprintk(MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); break; default: - dprintk(verbose, MANTIS_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); + dprintk(MANTIS_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); return -EINVAL; } mmwrite(0x00, MANTIS_GPIF_DOUT); return 0; } + +static int vp1034_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); + fe = mb86a16_attach(&vp1034_mb86a16_config, adapter); + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found MB86A16 DVB-S/DSS frontend @0x%02x", + vp1034_mb86a16_config.demod_address); + + } else { + return -1; + } + + mantis->fe = fe; + dprintk(MANTIS_ERROR, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp1034_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp1034_frontend_init, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/dvb/mantis/mantis_vp1034.h index 21948573b08..30269129066 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.h +++ b/drivers/media/dvb/mantis/mantis_vp1034.h @@ -23,13 +23,11 @@ #include "dvb_frontend.h" #include "mantis_common.h" -#include "mb86a16.h" #define MANTIS_VP_1034_DVB_S 0x0014 -extern struct mantis_hwconfig vp1034_mantis_config; -extern struct mb86a16_config vp1034_config; +extern struct mantis_hwconfig vp1034_config; extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage); -#endif // __MANTIS_VP1034_H +#endif /* __MANTIS_VP1034_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 90df80b80e1..1181fad3b27 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -18,24 +18,31 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp1041.h" #include "stb0899_reg.h" +#include "stb0899_drv.h" #include "stb0899_cfg.h" #include "stb6100_cfg.h" +#include "stb6100.h" +#include "lnbp21.h" #define MANTIS_MODEL_NAME "VP-1041" #define MANTIS_DEV_TYPE "DSS/DVB-S/DVB-S2" -struct mantis_hwconfig vp1041_mantis_config = { - .model_name = MANTIS_MODEL_NAME, - .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_188, - .baud_rate = MANTIS_BAUD_9600, - .parity = MANTIS_PARITY_NONE, - .bytes = 0, -}; - static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { // 0x0000000b , /* SYSREG */ @@ -258,7 +265,7 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { { 0xffff , 0xff }, }; -struct stb0899_config vp1041_config = { +struct stb0899_config vp1041_stb0899_config = { .init_dev = vp1041_stb0899_s1_init_1, .init_s2_demod = stb0899_s2_init_2, .init_s1_demod = vp1041_stb0899_s1_init_3, @@ -299,3 +306,55 @@ struct stb6100_config vp1041_stb6100_config = { .tuner_address = 0x60, .refclock = 27000000, }; + +static int vp1041_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + int err = 0; + + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + mantis_frontend_soft_reset(mantis); + msleep(250); + mantis->fe = stb0899_attach(&vp1041_stb0899_config, adapter); + if (mantis->fe) { + dprintk(MANTIS_ERROR, 1, + "found STB0899 DVB-S/DVB-S2 frontend @0x%02x", + vp1041_stb0899_config.demod_address); + + if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, adapter)) { + if (!lnbp21_attach(mantis->fe, adapter, 0, 0)) { + printk("%s: No LNBP21 found!\n", __func__); + } + } + } else { + return -EREMOTEIO; + } + } else { + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + + return -EIO; + } + + + dprintk(MANTIS_ERROR, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp1041_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp1041_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp1041.h b/drivers/media/dvb/mantis/mantis_vp1041.h index 2cc83a6e599..1ae5b3de808 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.h +++ b/drivers/media/dvb/mantis/mantis_vp1041.h @@ -21,17 +21,13 @@ #ifndef __MANTIS_VP1041_H #define __MANTIS_VP1041_H -#include "dvb_frontend.h" #include "mantis_common.h" -#include "stb0899_drv.h" -#include "stb6100.h" -#include "lnbp21.h" #define MANTIS_VP_1041_DVB_S2 0x0031 -#define TECHNISAT_SKYSTAR_HD2 0x0001 +#define SKYSTAR_HD2_10 0x0001 +#define SKYSTAR_HD2_20 0x0003 +#define CINERGY_S2_PCI_HD 0x1179 -extern struct mantis_hwconfig vp1041_mantis_config; -extern struct stb0899_config vp1041_config; -extern struct stb6100_config vp1041_stb6100_config; +extern struct mantis_hwconfig vp1041_config; -#endif // __MANTIS_VP1041_H +#endif /* __MANTIS_VP1041_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 1171e69b7e6..877329175d0 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -18,48 +18,59 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "tda1002x.h" #include "mantis_common.h" #include "mantis_vp2033.h" #define MANTIS_MODEL_NAME "VP-2033" #define MANTIS_DEV_TYPE "DVB-C" -struct mantis_hwconfig vp2033_mantis_config = { - .model_name = MANTIS_MODEL_NAME, - .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_204, - .baud_rate = MANTIS_BAUD_9600, - .parity = MANTIS_PARITY_NONE, - .bytes = 0, +struct tda1002x_config vp2033_tda1002x_cu1216_config = { + .demod_address = 0x18 >> 1, + .invert = 1, }; -struct tda1002x_config philips_cu1216_config = { +struct tda10023_config vp2033_tda10023_cu1216_config = { .demod_address = 0x18 >> 1, .invert = 1, }; -u8 read_pwm(struct mantis_pci *mantis) +static u8 read_pwm(struct mantis_pci *mantis) { + struct i2c_adapter *adapter = &mantis->adapter; + u8 b = 0xff; u8 pwm; struct i2c_msg msg[] = { - {.addr = 0x50,.flags = 0,.buf = &b,.len = 1}, - {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} + {.addr = 0x50, .flags = 0, .buf = &b, .len = 1}, + {.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1} }; - if ((i2c_transfer(&mantis->adapter, msg, 2) != 2) + if ((i2c_transfer(adapter, msg, 2) != 2) || (pwm == 0xff)) pwm = 0x48; return pwm; } -int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct mantis_pci *mantis = fe->dvb->priv; + struct i2c_adapter *adapter = &mantis->adapter; u8 buf[6]; - struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; + struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof (buf) }; int i; #define CU1216_IF 36125000 @@ -78,7 +89,7 @@ int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parame if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&mantis->adapter, &msg, 1) != 1) + if (i2c_transfer(adapter, &msg, 1) != 1) return -EIO; /* wait for the pll lock */ @@ -88,7 +99,7 @@ int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parame if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&mantis->adapter, &msg, 1) == 1 && (buf[0] & 0x40)) + if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40)) break; msleep(10); @@ -102,8 +113,58 @@ int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parame if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&mantis->adapter, &msg, 1) != 1) + if (i2c_transfer(adapter, &msg, 1) != 1) return -EIO; return 0; } + +static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + fe = tda10021_attach(&vp2033_tda1002x_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", + vp2033_tda1002x_cu1216_config.demod_address); + } else { + fe = tda10023_attach(&vp2033_tda10023_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + vp2033_tda1002x_cu1216_config.demod_address); + } + } + + if (fe) { + fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; + dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + } else { + return -1; + } + + mantis->fe = fe; + dprintk(MANTIS_DEBUG, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp2033_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp2033_frontend_init, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index fcf8b85be94..e6c5fe80f72 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -21,17 +21,10 @@ #ifndef __MANTIS_VP2033_H #define __MANTIS_VP2033_H -#include "dvb_frontend.h" #include "mantis_common.h" -#include "tda1002x.h" #define MANTIS_VP_2033_DVB_C 0x0008 -extern struct tda1002x_config philips_cu1216_config; -extern struct mantis_hwconfig vp2033_mantis_config; +extern struct mantis_hwconfig vp2033_config; -extern int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params); - -extern u8 read_pwm(struct mantis_pci *mantis); - -#endif // __MANTIS_VP2033_H +#endif /* __MANTIS_VP2033_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index ce73d6beb5c..51b082f7f91 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -18,22 +18,153 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "tda1002x.h" #include "mantis_common.h" #include "mantis_vp2040.h" #define MANTIS_MODEL_NAME "VP-2040" #define MANTIS_DEV_TYPE "DVB-C" -struct mantis_hwconfig vp2040_mantis_config = { +struct tda1002x_config vp2040_tda1002x_cu1216_config = { + .demod_address = 0x18 >> 1, + .invert = 1, +}; + +struct tda10023_config vp2040_tda10023_cu1216_config = { + .demod_address = 0x18 >> 1, + .invert = 1, +}; + +static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct mantis_pci *mantis = fe->dvb->priv; + struct i2c_adapter *adapter = &mantis->adapter; + + u8 buf[6]; + struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof (buf) }; + int i; + +#define CU1216_IF 36125000 +#define TUNER_MUL 62500 + + u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0xce; + buf[3] = (params->frequency < 150000000 ? 0x01 : + params->frequency < 445000000 ? 0x02 : 0x04); + buf[4] = 0xde; + buf[5] = 0x20; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(adapter, &msg, 1) != 1) + return -EIO; + + /* wait for the pll lock */ + msg.flags = I2C_M_RD; + msg.len = 1; + for (i = 0; i < 20; i++) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40)) + break; + + msleep(10); + } + + /* switch the charge pump to the lower current */ + msg.flags = 0; + msg.len = 2; + msg.buf = &buf[2]; + buf[2] &= ~0x40; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(adapter, &msg, 1) != 1) + return -EIO; + + return 0; +} + +static u8 read_pwm(struct mantis_pci *mantis) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + u8 b = 0xff; + u8 pwm; + struct i2c_msg msg[] = { + {.addr = 0x50, .flags = 0, .buf = &b, .len = 1}, + {.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1} + }; + + if ((i2c_transfer(adapter, msg, 2) != 2) + || (pwm == 0xff)) + pwm = 0x48; + + return pwm; +} + +static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + fe = tda10021_attach(&vp2040_tda1002x_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", + vp2040_tda1002x_cu1216_config.demod_address); + } else { + fe = tda10023_attach(&vp2040_tda10023_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + vp2040_tda1002x_cu1216_config.demod_address); + } + } + + if (fe) { + fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; + dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + } else { + return -1; + } + + mantis->fe = fe; + dprintk(MANTIS_DEBUG, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp2040_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_204, + .baud_rate = MANTIS_BAUD_9600, .parity = MANTIS_PARITY_NONE, .bytes = 0, -}; -struct tda10023_config tda10023_cu1216_config = { - .demod_address = 0x18 >> 1, - .invert = 1, + .frontend_init = vp2040_frontend_init, }; diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h index c7457543d8b..d125e219b68 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.h +++ b/drivers/media/dvb/mantis/mantis_vp2040.h @@ -21,15 +21,12 @@ #ifndef __MANTIS_VP2040_H #define __MANTIS_VP2040_H -#include "dvb_frontend.h" #include "mantis_common.h" -#include "tda1002x.h" #define MANTIS_VP_2040_DVB_C 0x0043 -#define TERRATEC_CINERGY_C_PCI 0x1178 -#define TECHNISAT_CABLESTAR_HD2 0x0002 +#define CINERGY_C 0x1178 +#define CABLESTAR_HD2 0x0002 -extern struct tda10023_config tda10023_cu1216_config; -extern struct mantis_hwconfig vp2040_mantis_config; +extern struct mantis_hwconfig vp2040_config; -#endif //__MANTIS_VP2040_H +#endif /* __MANTIS_VP2040_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index 9ca8040489d..4b974eeefa9 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -18,6 +18,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "zl10353.h" #include "mantis_common.h" #include "mantis_vp3030.h" @@ -28,15 +40,6 @@ struct zl10353_config mantis_vp3030_config = { #define MANTIS_MODEL_NAME "VP-3030" #define MANTIS_DEV_TYPE "DVB-T" -struct mantis_hwconfig vp3030_mantis_config = { - .model_name = MANTIS_MODEL_NAME, - .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_188, - .baud_rate = MANTIS_BAUD_9600, - .parity = MANTIS_PARITY_NONE, - .bytes = 0, -}; - int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { @@ -63,3 +66,31 @@ int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, return 0; } + +static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); + fe = zl10353_attach(&mantis_vp3030_config, adapter); + + if (!fe) + return -1; + + mantis->fe = fe; + dprintk(MANTIS_ERROR, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp3030_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp3030_frontend_init, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/dvb/mantis/mantis_vp3030.h index acc50a48e18..0a110ba5c1d 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.h +++ b/drivers/media/dvb/mantis/mantis_vp3030.h @@ -21,14 +21,10 @@ #ifndef __MANTIS_VP3030_H #define __MANTIS_VP3030_H -#include "dvb_frontend.h" #include "mantis_common.h" -#include "dvb-pll.h" -#include "zl10353.h" #define MANTIS_VP_3030_DVB_T 0x0024 -extern struct zl10353_config mantis_vp3030_config; -extern struct mantis_hwconfig vp3030_mantis_config; +extern struct mantis_hwconfig vp3030_config; -#endif // __MANTIS_VP3030_H +#endif /* __MANTIS_VP3030_H */ -- cgit v1.2.3-70-g09d2 From ad0ac434cb3b34640a4e81d7e80a1512c6e40253 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:41:52 -0300 Subject: V4L/DVB (13796): [Mantis] Add missing file in previous commit Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ioc.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_ioc.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ioc.h b/drivers/media/dvb/mantis/mantis_ioc.h new file mode 100644 index 00000000000..20526406723 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ioc.h @@ -0,0 +1,31 @@ +#ifndef __MANTIS_IOC_H +#define __MANTIS_IOC_H + +#define GPIF_A00 0x00 +#define GPIF_A01 0x01 +#define GPIF_A02 0x02 +#define GPIF_A03 0x03 +#define GPIF_A04 0x04 +#define GPIF_A05 0x05 +#define GPIF_A06 0x06 +#define GPIF_A07 0x07 +#define GPIF_A08 0x08 +#define GPIF_A09 0x09 +#define GPIF_A10 0x0a +#define GPIF_A11 0x0b + +#define GPIF_A12 0x0c +#define GPIF_A13 0x0d +#define GPIF_A14 0x0e + +enum mantis_stream_control { + STREAM_TO_HIF = 0, + STREAM_TO_CAM +}; + +extern int mantis_get_mac(struct mantis_pci *mantis); +extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); + +extern int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl); + +#endif /* __MANTIS_IOC_H */ -- cgit v1.2.3-70-g09d2 From 3e978a8284080d801d20cda377d9cf7c12fe68b9 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:56:35 -0300 Subject: V4L/DVB (13797): [Mantis/Hopper/TDA665x] Large overhaul, * Initial go at VP-3028, VP-3030 devices. * I2C communication improvements, * Add TDA665x support Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 11 ++ drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/tda665x.c | 257 +++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/tda665x.h | 52 +++++++ drivers/media/dvb/mantis/hopper_cards.c | 1 - drivers/media/dvb/mantis/mantis_cards.c | 11 +- drivers/media/dvb/mantis/mantis_dma.c | 3 +- drivers/media/dvb/mantis/mantis_dvb.c | 22 ++- drivers/media/dvb/mantis/mantis_i2c.c | 141 +++++++++++------ drivers/media/dvb/mantis/mantis_i2c.h | 3 + drivers/media/dvb/mantis/mantis_ioc.c | 42 ++--- drivers/media/dvb/mantis/mantis_vp3030.c | 52 +++---- 12 files changed, 479 insertions(+), 117 deletions(-) create mode 100644 drivers/media/dvb/frontends/tda665x.c create mode 100644 drivers/media/dvb/frontends/tda665x.h (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index a3b8b697349..7820ca084b1 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -587,6 +587,17 @@ config DVB_ATBM8830 help A DMB-TH tuner module. Say Y when you want to support this frontend. +config DVB_TDA665x + tristate "TDA665x tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + Support for tuner modules based on Philips TDA6650/TDA6651 chips. + Say Y when you want to support this chip. + + Currently supported tuners: + * Panasonic ENV57H12D5 (ET-50DT) + comment "Tools to develop new frontends" config DVB_DUMMY_FE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 47575cc7b69..59f7b880355 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_DVB_TDA10048) += tda10048.o obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o obj-$(CONFIG_DVB_S5H1411) += s5h1411.o obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o +obj-$(CONFIG_DVB_TDA665x) += tda665x.o obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb/frontends/tda665x.c new file mode 100644 index 00000000000..0732a2d38e1 --- /dev/null +++ b/drivers/media/dvb/frontends/tda665x.c @@ -0,0 +1,257 @@ +/* + TDA665x tuner driver + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#include "dvb_frontend.h" +#include "tda665x.h" + +struct tda665x_state { + struct dvb_frontend *fe; + struct i2c_adapter *i2c; + const struct tda665x_config *config; + + u32 frequency; + u32 bandwidth; +}; + +static int tda665x_read(struct tda665x_state *state, u8 *buf) +{ + const struct tda665x_config *config = state->config; + int err = 0; + struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD, .buf = buf, .len = 2 }; + + err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) + goto exit; + + return err; +exit: + printk("%s: I/O Error err=<%d>\n", __func__, err); + return err; +} + +static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length) +{ + const struct tda665x_config *config = state->config; + int err = 0; + struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = length }; + + err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) + goto exit; + + return err; +exit: + printk("%s: I/O Error err=<%d>\n", __func__, err); + return err; +} + +static int tda665x_get_state(struct dvb_frontend *fe, + enum tuner_param param, + struct tuner_state *tstate) +{ + struct tda665x_state *state = fe->tuner_priv; + int err = 0; + + switch (param) { + case DVBFE_TUNER_FREQUENCY: + tstate->frequency = state->frequency; + break; + case DVBFE_TUNER_BANDWIDTH: + break; + default: + printk("%s: Unknown parameter (param=%d)\n", __func__, param); + err = -EINVAL; + break; + } + + return err; +} + +static int tda665x_get_status(struct dvb_frontend *fe, u32 *status) +{ + struct tda665x_state *state = fe->tuner_priv; + u8 result = 0; + int err = 0; + + *status = 0; + + err = tda665x_read(state, &result); + if (err < 0) + goto exit; + + if ((result >> 6) & 0x01) { + printk("%s: Tuner Phase Locked\n", __func__); + *status = 1; + } + + return err; +exit: + printk("%s: I/O Error\n", __func__); + return err; +} + +static int tda665x_set_state(struct dvb_frontend *fe, + enum tuner_param param, + struct tuner_state *tstate) +{ + struct tda665x_state *state = fe->tuner_priv; + const struct tda665x_config *config = state->config; + u32 frequency, status = 0; + u8 buf[4]; + int err = 0; + + if (param & DVBFE_TUNER_FREQUENCY) { + + frequency = tstate->frequency; + if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) { + printk("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency); + return -EINVAL; + } + + frequency += config->frequency_offst; + frequency *= config->ref_multiplier; + frequency += config->ref_divider >> 1; + frequency /= config->ref_divider; + + buf[0] = (u8 ) (frequency & 0x7f00) >> 8; + buf[1] = (u8 ) (frequency & 0x00ff) >> 0; + buf[2] = 0x80 | 0x40 | 0x02; + buf[3] = 0x00; + + /* restore frequency */ + frequency = tstate->frequency; + + if (frequency < 153000000) { + /* VHF-L */ + buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */ + if (frequency < 68000000) + buf[3] |= 0x40; /* 83uA */ + if (frequency < 1040000000) + buf[3] |= 0x60; /* 122uA */ + if (frequency < 1250000000) + buf[3] |= 0x80; /* 163uA */ + else + buf[3] |= 0xa0; /* 254uA */ + } else if (frequency < 438000000) { + /* VHF-H */ + buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */ + if (frequency < 230000000) + buf[3] |= 0x40; + if (frequency < 300000000) + buf[3] |= 0x60; + else + buf[3] |= 0x80; + } else { + /* UHF */ + buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */ + if (frequency < 470000000) + buf[3] |= 0x60; + if (frequency < 526000000) + buf[3] |= 0x80; + else + buf[3] |= 0xa0; + } + + /* Set params */ + err = tda665x_write(state, buf, 5); + if (err < 0) + goto exit; + + /* sleep for some time */ + printk("%s: Waiting to Phase LOCK\n", __func__); + msleep(20); + /* check status */ + err = tda665x_get_status(fe, &status); + if (err < 0) + goto exit; + + if (status == 1) { + printk("%s: Tuner Phase locked: status=%d\n", __func__, status); + state->frequency = frequency; /* cache successful state */ + } else { + printk("%s: No Phase lock: status=%d\n", __func__, status); + } + } else { + printk("%s: Unknown parameter (param=%d)\n", __func__, param); + return -EINVAL; + } + + return 0; +exit: + printk("%s: I/O Error\n", __func__); + return err; +} + +static int tda665x_release(struct dvb_frontend *fe) +{ + struct tda665x_state *state = fe->tuner_priv; + + fe->tuner_priv = NULL; + kfree(state); + return 0; +} + +static struct dvb_tuner_ops tda665x_ops = { + + .set_state = tda665x_set_state, + .get_state = tda665x_get_state, + .get_status = tda665x_get_status, + .release = tda665x_release +}; + +struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, + const struct tda665x_config *config, + struct i2c_adapter *i2c) +{ + struct tda665x_state *state = NULL; + struct dvb_tuner_info *info; + + state = kzalloc(sizeof (struct tda665x_state), GFP_KERNEL); + if (state == NULL) + goto exit; + + state->config = config; + state->i2c = i2c; + state->fe = fe; + fe->tuner_priv = state; + fe->ops.tuner_ops = tda665x_ops; + info = &fe->ops.tuner_ops.info; + + memcpy(info->name, config->name, sizeof (config->name)); + info->frequency_min = config->frequency_min; + info->frequency_max = config->frequency_max; + info->frequency_step = config->frequency_offst; + + printk("%s: Attaching TDA665x (%s) tuner\n", __func__, info->name); + + return fe; + +exit: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(tda665x_attach); + +MODULE_DESCRIPTION("TDA665x driver"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/tda665x.h b/drivers/media/dvb/frontends/tda665x.h new file mode 100644 index 00000000000..c0b544d8ef5 --- /dev/null +++ b/drivers/media/dvb/frontends/tda665x.h @@ -0,0 +1,52 @@ +/* + TDA665x tuner driver + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __TDA665x_H +#define __TDA665x_H + +struct tda665x_config { + char name[128]; + + u8 addr; + u32 frequency_min; + u32 frequency_max; + u32 frequency_offst; + u32 ref_multiplier; + u32 ref_divider; +}; + +#if defined(CONFIG_DVB_TDA665x) || (defined(CONFIG_DVB_TDA665x_MODULE) && defined(MODULE)) + +extern struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, + const struct tda665x_config *config, + struct i2c_adapter *i2c); + +#else + +static inline struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, + const struct tda665x_config *config, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__); + return NULL; +} + +#endif /* CONFIG_DVB_TDA665x */ + +#endif /* __TDA665x_H */ diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c index 749e3f3dd06..01a9ff07d77 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -219,7 +219,6 @@ static void __devexit hopper_pci_remove(struct pci_dev *pdev) struct mantis_pci *mantis = pci_get_drvdata(pdev); if (mantis) { -// mantis_uart_exit(mantis); mantis_dvb_exit(mantis); mantis_dma_exit(mantis); mantis_i2c_exit(mantis); diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index d486c7fcb45..638177ce72a 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -50,7 +50,6 @@ static char *label[10] = { "RACK" }; - static irqreturn_t mantis_irq_handler(int irq, void *dev_id) { u32 stat = 0, mask = 0, lstat = 0, mstat = 0; @@ -199,6 +198,14 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_dev return err; +fail7: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err); + mantis_uart_exit(mantis); + +fail6: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis CA exit! <%d>", err); + mantis_ca_exit(mantis); + fail5: dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB exit! <%d>", err); mantis_dvb_exit(mantis); @@ -228,8 +235,6 @@ static void __devexit mantis_pci_remove(struct pci_dev *pdev) struct mantis_pci *mantis = pci_get_drvdata(pdev); if (mantis) { - mantis_uart_exit(mantis); -// mantis_ca_exit(mantis); mantis_dvb_exit(mantis); mantis_dma_exit(mantis); mantis_i2c_exit(mantis); diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index 8ebcd96b2b7..eab3645f7ac 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -153,8 +153,7 @@ int mantis_dma_init(struct mantis_pci *mantis) if (mantis_alloc_buffers(mantis) < 0) { dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer"); - // Stop RISC Engine -// mmwrite(mmread(MANTIS_DMA_CTL) & ~MANTIS_RISC_EN, MANTIS_DMA_CTL); + /* Stop RISC Engine */ mmwrite(0, MANTIS_DMA_CTL); goto err; diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index be911d76daa..42f658b06a6 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -252,14 +252,19 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) err5: tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); + err4: mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); + err3: mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); + err2: dvb_dmxdev_release(&mantis->dmxdev); + err1: dvb_dmx_release(&mantis->demux); + err0: dvb_unregister_adapter(&mantis->dvb_adapter); @@ -271,21 +276,24 @@ int __devexit mantis_dvb_exit(struct mantis_pci *mantis) { int err; - err = mantis_frontend_shutdown(mantis); - if (err != 0) - dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); + if (mantis->fe) { +// mantis_ca_exit(mantis); + err = mantis_frontend_shutdown(mantis); + if (err != 0) + dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); + + dvb_unregister_frontend(mantis->fe); + } -// mantis_ca_exit(mantis); tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); + dvb_dmxdev_release(&mantis->dmxdev); dvb_dmx_release(&mantis->demux); - if (mantis->fe) - dvb_unregister_frontend(mantis->fe); - dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter"); dvb_unregister_adapter(&mantis->dvb_adapter); diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index ba55f0a9a10..16b9e7e77b8 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -35,38 +35,9 @@ #define I2C_HW_B_MANTIS 0x1c -static int mantis_ack_wait(struct mantis_pci *mantis) -{ - int rc = 0; - u32 timeout = 0; - - if (wait_event_timeout(mantis->i2c_wq, - mantis->mantis_int_stat & MANTIS_INT_I2CDONE, - msecs_to_jiffies(50)) == -ERESTARTSYS) { - - dprintk(MANTIS_DEBUG, 1, "Master !I2CDONE"); - rc = -EREMOTEIO; - } - - while (!(mantis->mantis_int_stat & MANTIS_INT_I2CRACK)) { - dprintk(MANTIS_DEBUG, 1, "Waiting for Slave RACK"); - mantis->mantis_int_stat = mmread(MANTIS_INT_STAT); - msleep(5); - timeout++; - if (timeout > 500) { - dprintk(MANTIS_ERROR, 1, "Slave RACK Fail !"); - rc = -EREMOTEIO; - break; - } - } - udelay(350); - - return rc; -} - static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) { - u32 rxd, i; + u32 rxd, i, stat, trials; dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); @@ -82,10 +53,15 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(rxd, MANTIS_I2CDATA_CTL); - if (mantis_ack_wait(mantis) != 0) { - dprintk(MANTIS_DEBUG, 1, "ACK failed"); - return -EREMOTEIO; + + /* wait for xfer completion */ + for (trials = 0; trials < 100; trials++) { + udelay(500); + stat = mmread(MANTIS_INT_STAT); + if (stat & MANTIS_INT_I2CDONE) + break; } + rxd = mmread(MANTIS_I2CDATA_CTL); msg->buf[i] = (u8)((rxd >> 8) & 0xFF); dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]); @@ -98,7 +74,7 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg) { int i; - u32 txd = 0; + u32 txd = 0, stat, trials; dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); @@ -115,9 +91,13 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(txd, MANTIS_I2CDATA_CTL); - if (mantis_ack_wait(mantis) != 0) { - dprintk(MANTIS_DEBUG, 1, "ACK failed"); - return -EREMOTEIO; + + /* wait for xfer completion */ + for (trials = 0; trials < 100; trials++) { + udelay(500); + stat = mmread(MANTIS_INT_STAT); + if (stat & MANTIS_INT_I2CDONE) + break; } } dprintk(MANTIS_INFO, 0, "]\n"); @@ -127,20 +107,77 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { - int ret = 0, i; + int ret = 0, i = 0, trials; + u32 stat, data, txd; struct mantis_pci *mantis; + struct mantis_hwconfig *config; mantis = i2c_get_adapdata(adapter); + BUG_ON(!mantis); + config = mantis->hwconfig; + BUG_ON(!config); + + dprintk(MANTIS_DEBUG, 1, "Messages:%d", num); mutex_lock(&mantis->i2c_lock); - for (i = 0; i < num; i++) { - if (msgs[i].flags & I2C_M_RD) - ret = mantis_i2c_read(mantis, &msgs[i]); - else - ret = mantis_i2c_write(mantis, &msgs[i]); - - if (ret < 0) - goto bail_out; + + while (i < num) { + /* Byte MODE */ + if (((i + 1) < num) && + (msgs[i].len < 2) && + (msgs[i + 1].len < 2) && + (msgs[i + 1].flags & I2C_M_RD)) { + + dprintk(MANTIS_DEBUG, 0, " Byte MODE:\n"); + + /* Read operation */ + txd = msgs[i].addr << 25 | (0x1 << 24) + | (msgs[i].buf[0] << 16) + | MANTIS_I2C_RATE_3; + + mmwrite(txd, MANTIS_I2CDATA_CTL); + /* wait for xfer completion */ + for (trials = 0; trials < 100; trials++) { + udelay(500); + stat = mmread(MANTIS_INT_STAT); + if (stat & MANTIS_INT_I2CDONE) + break; + } + + /* check for xfer completion */ + if (stat & MANTIS_INT_I2CDONE) { + /* check xfer was acknowledged */ + if (stat & MANTIS_INT_I2CRACK) { + data = mmread(MANTIS_I2CDATA_CTL); + msgs[i + 1].buf[0] = (data >> 8) & 0xff; + dprintk(MANTIS_DEBUG, 0, " Byte <%d> RXD=0x%02x [%02x]\n", 0x0, data, msgs[i + 1].buf[0]); + } else { + /* I/O error */ + dprintk(MANTIS_ERROR, 1, " I/O error, LINE:%d", __LINE__); + ret = -EIO; + break; + } + } else { + /* I/O error */ + dprintk(MANTIS_ERROR, 1, " I/O error, LINE:%d", __LINE__); + ret = -EIO; + break; + } + i += 2; /* Write/Read operation in one go */ + } + + if (i < num) { + if (msgs[i].flags & I2C_M_RD) + ret = mantis_i2c_read(mantis, &msgs[i]); + else + ret = mantis_i2c_write(mantis, &msgs[i]); + + i++; + if (ret < 0) + goto bail_out; + } + } + mutex_unlock(&mantis->i2c_lock); return num; @@ -189,9 +226,9 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) intstat = mmread(MANTIS_INT_STAT); intmask = mmread(MANTIS_INT_MASK); mmwrite(intstat, MANTIS_INT_STAT); - mmwrite(intmask | MANTIS_INT_I2CDONE, MANTIS_INT_MASK); - - dprintk(MANTIS_DEBUG, 1, "Status=<%02x> Mask=<%02x>", intstat, intmask); + dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt"); + intmask = mmread(MANTIS_INT_MASK); + mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK); return 0; } @@ -199,6 +236,12 @@ EXPORT_SYMBOL_GPL(mantis_i2c_init); int __devexit mantis_i2c_exit(struct mantis_pci *mantis) { + u32 intmask; + + dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt"); + intmask = mmread(MANTIS_INT_MASK); + mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK); + dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter"); return i2c_del_adapter(&mantis->adapter); } diff --git a/drivers/media/dvb/mantis/mantis_i2c.h b/drivers/media/dvb/mantis/mantis_i2c.h index 1e49ecfeee3..d40da4fa000 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.h +++ b/drivers/media/dvb/mantis/mantis_i2c.h @@ -1,6 +1,9 @@ #ifndef __MANTIS_I2C_H #define __MANTIS_I2C_H +#define I2C_STOP (1 << 0) +#define I2C_READ (1 << 1) + extern int mantis_i2c_init(struct mantis_pci *mantis); extern int mantis_i2c_exit(struct mantis_pci *mantis); diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c index 4700088f038..448e2c3e344 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.c +++ b/drivers/media/dvb/mantis/mantis_ioc.c @@ -36,13 +36,14 @@ #include "mantis_reg.h" #include "mantis_ioc.h" -static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +static int read_eeprom_bytes(struct mantis_pci *mantis, u8 reg, u8 *data, u8 length) { struct i2c_adapter *adapter = &mantis->adapter; - int err; + u8 buf = reg; + struct i2c_msg msg[] = { - { .addr = 0x50, .flags = 0, .buf = data, .len = 1 }, + { .addr = 0x50, .flags = 0, .buf = &buf, .len = 1 }, { .addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = length }, }; @@ -56,32 +57,12 @@ static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) return 0; } - -static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) -{ - struct i2c_adapter *adapter = &mantis->adapter; - int err; - - struct i2c_msg msg = { .addr = 0x50, .flags = 0, .buf = data, .len = length }; - - err = i2c_transfer(adapter, &msg, 1); - if (err < 0) { - dprintk(MANTIS_ERROR, 1, "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", - err, length, data[0], data[1]); - - return err; - } - - return 0; -} - int mantis_get_mac(struct mantis_pci *mantis) { int err; + u8 mac_addr[6] = {0}; - mantis->mac_address[0] = 0x08; - - err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6); + err = read_eeprom_bytes(mantis, 0x08, mac_addr, 6); if (err < 0) { dprintk(MANTIS_ERROR, 1, "ERROR: Mantis EEPROM read error <%d>", err); @@ -90,9 +71,12 @@ int mantis_get_mac(struct mantis_pci *mantis) dprintk(MANTIS_ERROR, 0, " MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n", - mantis->mac_address[0], mantis->mac_address[1], - mantis->mac_address[2], mantis->mac_address[3], - mantis->mac_address[4], mantis->mac_address[5]); + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5]); return 0; } @@ -103,12 +87,14 @@ void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) { u32 cur; + dprintk(MANTIS_DEBUG, 1, "Set Bit <%d> to <%d>", bitpos, value); cur = mmread(MANTIS_GPIF_ADDR); if (value) mantis->gpio_status = cur | (1 << bitpos); else mantis->gpio_status = cur & (~(1 << bitpos)); + dprintk(MANTIS_DEBUG, 1, "GPIO Value <%02x>", mantis->gpio_status); mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR); mmwrite(0x00, MANTIS_GPIF_DOUT); } diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index 4b974eeefa9..9efcfa7b8ab 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -30,46 +30,41 @@ #include "dvb_net.h" #include "zl10353.h" +#include "tda665x.h" #include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp3030.h" struct zl10353_config mantis_vp3030_config = { - .demod_address = 0x0f, + .demod_address = 0x0f, +}; + +struct tda665x_config env57h12d5_config = { + .name = "ENV57H12D5 (ET-50DT)", + .addr = 0x60, + .frequency_min = 47000000, + .frequency_max = 862000000, + .frequency_offst = 3616667, + .ref_multiplier = 6, /* 1/6 MHz */ + .ref_divider = 100000, /* 1/6 MHz */ }; #define MANTIS_MODEL_NAME "VP-3030" #define MANTIS_DEV_TYPE "DVB-T" -int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params) -{ - u8 buf[4]; - int rc; - struct mantis_pci *mantis = fe->dvb->priv; - - struct i2c_msg tuner_msg = { - .addr = 0x60, - .flags = 0, - .buf = buf, - .len = sizeof (buf) - }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) - return -EINVAL; - rc = i2c_transfer(&mantis->adapter, &tuner_msg, 1); - if (rc != 1) { - printk("%s: I2C Transfer returned [%d]\n", __func__, rc); - return -EIO; - } - msleep_interruptible(1); - printk("%s: Send params to tuner ok!!!\n", __func__); - - return 0; -} static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) { struct i2c_adapter *adapter = &mantis->adapter; + struct mantis_hwconfig *config = mantis->hwconfig; + int err = 0; + + gpio_set_bits(mantis, config->reset, 0); + msleep(100); + err = mantis_frontend_power(mantis, POWER_ON); + msleep(100); + gpio_set_bits(mantis, config->reset, 1); dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); fe = zl10353_attach(&mantis_vp3030_config, adapter); @@ -77,6 +72,7 @@ static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * if (!fe) return -1; + tda665x_attach(fe, &env57h12d5_config, adapter); mantis->fe = fe; dprintk(MANTIS_ERROR, 1, "Done!"); @@ -93,4 +89,6 @@ struct mantis_hwconfig vp3030_config = { .bytes = 0, .frontend_init = vp3030_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, }; -- cgit v1.2.3-70-g09d2 From bc832fa2c0310c25ed60204616ccef4f8db088f3 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:57:28 -0300 Subject: V4L/DVB (13798): [Mantis] Enable power for all cards, use byte mode only on relevant devices Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/hopper_vp3028.c | 27 ++++++++++++----- drivers/media/dvb/mantis/mantis_common.h | 13 ++++++-- drivers/media/dvb/mantis/mantis_i2c.c | 47 ++++++++++++++++++++++------- drivers/media/dvb/mantis/mantis_vp1033.c | 36 ++++++++++++++++------ drivers/media/dvb/mantis/mantis_vp1034.c | 32 +++++++++++++++----- drivers/media/dvb/mantis/mantis_vp2033.c | 50 +++++++++++++++++++++---------- drivers/media/dvb/mantis/mantis_vp2040.c | 51 +++++++++++++++++++++----------- drivers/media/dvb/mantis/mantis_vp3030.c | 22 ++++++++++---- 8 files changed, 203 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c index ba0c7e58b7a..16b39d3b9ac 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.c +++ b/drivers/media/dvb/mantis/hopper_vp3028.c @@ -45,17 +45,30 @@ struct zl10353_config hopper_vp3028_config = { static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) { struct i2c_adapter *adapter = &mantis->adapter; + struct mantis_hwconfig *config = mantis->hwconfig; int err = 0; + gpio_set_bits(mantis, config->reset, 0); + msleep(100); err = mantis_frontend_power(mantis, POWER_ON); - mantis_frontend_soft_reset(mantis); - - dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); - fe = zl10353_attach(&hopper_vp3028_config, adapter); - - if (!fe) - return -1; + msleep(100); + gpio_set_bits(mantis, config->reset, 1); + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + msleep(250); + dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); + fe = zl10353_attach(&hopper_vp3028_config, adapter); + + if (!fe) + return -1; + } else { + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + + return -EIO; + } dprintk(MANTIS_ERROR, 1, "Done!"); return 0; diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index e912c5962e3..6ae3aabe560 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -32,6 +32,7 @@ #define MANTIS_NOTICE 1 #define MANTIS_INFO 2 #define MANTIS_DEBUG 3 +#define MANTIS_TMG 9 #define dprintk(y, z, format, arg...) do { \ if (z) { \ @@ -43,6 +44,8 @@ printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ else if ((mantis->verbose > MANTIS_DEBUG) && (mantis->verbose > y)) \ printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + else if ((mantis->verbose > MANTIS_TMG) && (mantis->verbose > y)) \ + printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ } else { \ if (mantis->verbose > y) \ printk(format , ##arg); \ @@ -54,9 +57,6 @@ #define mmwrite(dat, addr) mwrite((dat), (mantis->mmio + (addr))) #define mmread(addr) mread(mantis->mmio + (addr)) -#define mmand(dat, addr) mmwrite((dat) & mmread(addr), addr) -#define mmor(dat, addr) mmwrite((dat) | mmread(addr), addr) -#define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr) #define MANTIS_TS_188 0 #define MANTIS_TS_204 1 @@ -75,6 +75,11 @@ .driver_data = (unsigned long) (__configptr) \ } +enum mantis_i2c_mode { + MANTIS_PAGE_MODE = 0, + MANTIS_BYTE_MODE, +}; + struct mantis_pci; struct mantis_hwconfig { @@ -91,6 +96,8 @@ struct mantis_hwconfig { u8 power; u8 reset; + + enum mantis_i2c_mode i2c_mode; }; struct mantis_pci { diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 16b9e7e77b8..758f32a63b2 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -35,6 +35,8 @@ #define I2C_HW_B_MANTIS 0x1c +#define TRIALS 10000 + static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) { u32 rxd, i, stat, trials; @@ -55,13 +57,25 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) mmwrite(rxd, MANTIS_I2CDATA_CTL); /* wait for xfer completion */ - for (trials = 0; trials < 100; trials++) { - udelay(500); + for (trials = 0; trials < TRIALS; trials++) { + msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; } + dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials); + + /* wait for xfer completion */ + for (trials = 0; trials < TRIALS; trials++) { + stat = mmread(MANTIS_INT_STAT); + if (stat & MANTIS_INT_I2CRACK) + break; + msleep(1); + } + + dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials); + rxd = mmread(MANTIS_I2CDATA_CTL); msg->buf[i] = (u8)((rxd >> 8) & 0xFF); dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]); @@ -93,12 +107,24 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg mmwrite(txd, MANTIS_I2CDATA_CTL); /* wait for xfer completion */ - for (trials = 0; trials < 100; trials++) { - udelay(500); + for (trials = 0; trials < TRIALS; trials++) { + msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; } + + dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials); + + /* wait for xfer completion */ + for (trials = 0; trials < TRIALS; trials++) { + stat = mmread(MANTIS_INT_STAT); + if (stat & MANTIS_INT_I2CRACK) + break; + msleep(1); + } + + dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials); } dprintk(MANTIS_INFO, 0, "]\n"); @@ -122,10 +148,11 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in while (i < num) { /* Byte MODE */ - if (((i + 1) < num) && - (msgs[i].len < 2) && - (msgs[i + 1].len < 2) && - (msgs[i + 1].flags & I2C_M_RD)) { + if ((config->i2c_mode & MANTIS_BYTE_MODE) && + ((i + 1) < num) && + (msgs[i].len < 2) && + (msgs[i + 1].len < 2) && + (msgs[i + 1].flags & I2C_M_RD)) { dprintk(MANTIS_DEBUG, 0, " Byte MODE:\n"); @@ -136,8 +163,8 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in mmwrite(txd, MANTIS_I2CDATA_CTL); /* wait for xfer completion */ - for (trials = 0; trials < 100; trials++) { - udelay(500); + for (trials = 0; trials < TRIALS; trials++) { + msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index f2092ce9c4b..0bea6e89f55 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -31,7 +31,10 @@ #include "stv0299.h" #include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp1033.h" +#include "mantis_reg.h" u8 lgtdqcs001f_inittab[] = { 0x01, 0x15, @@ -163,19 +166,32 @@ static int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * { struct i2c_adapter *adapter = &mantis->adapter; - dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); - fe = stv0299_attach(&lgtdqcs001f_config, adapter); + int err = 0; - if (fe) { - fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; - dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x", - lgtdqcs001f_config.demod_address); + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + mantis_frontend_soft_reset(mantis); + msleep(250); - dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success"); + dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); + fe = stv0299_attach(&lgtdqcs001f_config, adapter); + + if (fe) { + fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; + dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x", + lgtdqcs001f_config.demod_address); + + dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success"); + } else { + return -1; + } } else { - return -1; - } + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + return -EIO; + } mantis->fe = fe; dprintk(MANTIS_ERROR, 1, "Done!"); @@ -192,4 +208,6 @@ struct mantis_hwconfig vp1033_config = { .bytes = 0, .frontend_init = vp1033_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, }; diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 40778ec8f46..98a4ec89f04 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -32,6 +32,7 @@ #include "mb86a16.h" #include "mantis_common.h" #include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp1034.h" #include "mantis_reg.h" @@ -74,17 +75,30 @@ static int vp1034_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * { struct i2c_adapter *adapter = &mantis->adapter; - dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); - fe = mb86a16_attach(&vp1034_mb86a16_config, adapter); - if (fe) { - dprintk(MANTIS_ERROR, 1, - "found MB86A16 DVB-S/DSS frontend @0x%02x", - vp1034_mb86a16_config.demod_address); + int err = 0; + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + mantis_frontend_soft_reset(mantis); + msleep(250); + + dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); + fe = mb86a16_attach(&vp1034_mb86a16_config, adapter); + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found MB86A16 DVB-S/DSS frontend @0x%02x", + vp1034_mb86a16_config.demod_address); + + } else { + return -1; + } } else { - return -1; - } + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + return -EIO; + } mantis->fe = fe; dprintk(MANTIS_ERROR, 1, "Done!"); @@ -101,4 +115,6 @@ struct mantis_hwconfig vp1034_config = { .bytes = 0, .frontend_init = vp1034_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, }; diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 877329175d0..cef108c5ffc 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -31,6 +31,8 @@ #include "tda1002x.h" #include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp2033.h" #define MANTIS_MODEL_NAME "VP-2033" @@ -123,32 +125,46 @@ static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * { struct i2c_adapter *adapter = &mantis->adapter; - dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - fe = tda10021_attach(&vp2033_tda1002x_cu1216_config, - adapter, - read_pwm(mantis)); + int err = 0; - if (fe) { - dprintk(MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", - vp2033_tda1002x_cu1216_config.demod_address); - } else { - fe = tda10023_attach(&vp2033_tda10023_cu1216_config, + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + mantis_frontend_soft_reset(mantis); + msleep(250); + + dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + fe = tda10021_attach(&vp2033_tda1002x_cu1216_config, adapter, read_pwm(mantis)); if (fe) { dprintk(MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", vp2033_tda1002x_cu1216_config.demod_address); + } else { + fe = tda10023_attach(&vp2033_tda10023_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + vp2033_tda1002x_cu1216_config.demod_address); + } } - } - if (fe) { - fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; - dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + if (fe) { + fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; + dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + } else { + return -1; + } } else { - return -1; + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + + return -EIO; } mantis->fe = fe; @@ -167,4 +183,6 @@ struct mantis_hwconfig vp2033_config = { .bytes = 0, .frontend_init = vp2033_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, }; diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index 51b082f7f91..e2019884ac3 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -31,6 +31,8 @@ #include "tda1002x.h" #include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp2040.h" #define MANTIS_MODEL_NAME "VP-2040" @@ -123,34 +125,47 @@ static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * { struct i2c_adapter *adapter = &mantis->adapter; - dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - fe = tda10021_attach(&vp2040_tda1002x_cu1216_config, - adapter, - read_pwm(mantis)); + int err = 0; - if (fe) { - dprintk(MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", - vp2040_tda1002x_cu1216_config.demod_address); - } else { - fe = tda10023_attach(&vp2040_tda10023_cu1216_config, + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + mantis_frontend_soft_reset(mantis); + msleep(250); + + dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + fe = tda10021_attach(&vp2040_tda1002x_cu1216_config, adapter, read_pwm(mantis)); if (fe) { dprintk(MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", vp2040_tda1002x_cu1216_config.demod_address); + } else { + fe = tda10023_attach(&vp2040_tda10023_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + vp2040_tda1002x_cu1216_config.demod_address); + } } - } - if (fe) { - fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; - dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + if (fe) { + fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; + dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + } else { + return -1; + } } else { - return -1; - } + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + return -EIO; + } mantis->fe = fe; dprintk(MANTIS_DEBUG, 1, "Done!"); @@ -167,4 +182,6 @@ struct mantis_hwconfig vp2040_config = { .bytes = 0, .frontend_init = vp2040_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, }; diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index 9efcfa7b8ab..a44fac3aabc 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -66,13 +66,23 @@ static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * msleep(100); gpio_set_bits(mantis, config->reset, 1); - dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); - fe = zl10353_attach(&mantis_vp3030_config, adapter); + if (err == 0) { + msleep(250); + dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); + fe = zl10353_attach(&mantis_vp3030_config, adapter); - if (!fe) - return -1; + if (!fe) + return -1; - tda665x_attach(fe, &env57h12d5_config, adapter); + tda665x_attach(fe, &env57h12d5_config, adapter); + } else { + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + + return -EIO; + + } mantis->fe = fe; dprintk(MANTIS_ERROR, 1, "Done!"); @@ -91,4 +101,6 @@ struct mantis_hwconfig vp3030_config = { .frontend_init = vp3030_frontend_init, .power = GPIF_A12, .reset = GPIF_A13, + + .i2c_mode = MANTIS_BYTE_MODE }; -- cgit v1.2.3-70-g09d2 From 68fe255cd15cf1fe04877fbbb0eafe80c43eff5d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 09:01:35 -0300 Subject: V4L/DVB (13799): [Mantis] Unregister frontend Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 42f658b06a6..9d9c5582ada 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -252,7 +252,8 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) err5: tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); - + dvb_unregister_frontend(mantis->fe); + dvb_frontend_detach(mantis->fe); err4: mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); @@ -281,7 +282,7 @@ int __devexit mantis_dvb_exit(struct mantis_pci *mantis) err = mantis_frontend_shutdown(mantis); if (err != 0) dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); - + dvb_frontend_detach(mantis->fe); dvb_unregister_frontend(mantis->fe); } -- cgit v1.2.3-70-g09d2 From 281859179f731b28aae78d13b2e8720219492000 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 09:02:00 -0300 Subject: V4L/DVB (13800): [Mantis] I2C optimization. Required delay is much lesser than 1mS. Do not wait, keep looping instead. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_i2c.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 758f32a63b2..9d2b51d2e4b 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -58,7 +58,6 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) /* wait for xfer completion */ for (trials = 0; trials < TRIALS; trials++) { - msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; @@ -71,7 +70,6 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CRACK) break; - msleep(1); } dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials); @@ -108,7 +106,6 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg /* wait for xfer completion */ for (trials = 0; trials < TRIALS; trials++) { - msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; @@ -121,7 +118,6 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CRACK) break; - msleep(1); } dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials); @@ -164,7 +160,6 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in mmwrite(txd, MANTIS_I2CDATA_CTL); /* wait for xfer completion */ for (trials = 0; trials < TRIALS; trials++) { - msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; -- cgit v1.2.3-70-g09d2 From 5dd83a35bea908ebb8243d67d8c251eed2bb5cc8 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 06:15:27 -0300 Subject: V4L/DVB (13801): [MB86A16] Use the search callback Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 45 ++++++++++++++++------------------- 1 file changed, 21 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index eddb35baaf0..33387b78d85 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1487,16 +1487,19 @@ static int mb86a16_set_fe(struct mb86a16_state *state) } else { dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC"); SEQ_set(state, 1); + ret = -1; } } } else { dprintk (verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); + ret = -1; } sync = sync_chk(state, &junk); if (sync) { dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******"); freqerr_chk(state, state->frequency, state->srate, 1); + ret = 0; break; } } @@ -1610,33 +1613,21 @@ err: return -EREMOTEIO; } -#define MB86A16_FE_ALGO 1 - -static int mb86a16_frontend_algo(struct dvb_frontend *fe) -{ - return MB86A16_FE_ALGO; -} - -static int mb86a16_set_frontend(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p, - unsigned int mode_flags, - int *delay, - fe_status_t *status) +static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) { - int ret = 0; struct mb86a16_state *state = fe->demodulator_priv; - if (p != NULL) { - state->frequency = p->frequency / 1000; - state->srate = p->u.qpsk.symbol_rate / 1000; - ret = mb86a16_set_fe(state); - } - if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) - mb86a16_read_status(fe, status); + state->frequency = p->frequency / 1000; + state->srate = p->u.qpsk.symbol_rate / 1000; - *delay = HZ/3000; + if (!mb86a16_set_fe(state)) { + dprintk(verbose, MB86A16_ERROR, 1, "Succesfully acquired LOCK"); + return DVBFE_ALGO_SEARCH_SUCCESS; + } - return ret; + dprintk(verbose, MB86A16_ERROR, 1, "Lock acquisition failed!"); + return DVBFE_ALGO_SEARCH_FAILED; } static void mb86a16_release(struct dvb_frontend *fe) @@ -1809,6 +1800,11 @@ static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } +static enum dvbfe_algo mb86a16_frontend_algo(struct dvb_frontend *fe) +{ + return DVBFE_ALGO_CUSTOM; +} + static struct dvb_frontend_ops mb86a16_ops = { .info = { .name = "Fujitsu MB86A16 DVB-S", @@ -1826,9 +1822,10 @@ static struct dvb_frontend_ops mb86a16_ops = { FE_CAN_FEC_AUTO }, .release = mb86a16_release, - .tune = mb86a16_set_frontend, - .read_status = mb86a16_read_status, + .get_frontend_algo = mb86a16_frontend_algo, + .search = mb86a16_search, + .read_status = mb86a16_read_status, .init = mb86a16_init, .sleep = mb86a16_sleep, .read_status = mb86a16_read_status, -- cgit v1.2.3-70-g09d2 From 0bdc799b8b82cf61c86604291c53998febc96403 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 06:17:54 -0300 Subject: V4L/DVB (13802): [Mantis/Hopper] Fix all build related warnings Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/hopper_cards.c | 4 ---- drivers/media/dvb/mantis/hopper_vp3028.c | 1 - drivers/media/dvb/mantis/mantis_ca.c | 1 - drivers/media/dvb/mantis/mantis_cards.c | 13 ------------- drivers/media/dvb/mantis/mantis_dvb.c | 1 - drivers/media/dvb/mantis/mantis_evm.c | 1 - drivers/media/dvb/mantis/mantis_hif.c | 17 ----------------- drivers/media/dvb/mantis/mantis_ioc.c | 1 - drivers/media/dvb/mantis/mantis_pcmcia.c | 1 - drivers/media/dvb/mantis/mantis_uart.c | 7 +++---- drivers/media/dvb/mantis/mantis_vp1033.c | 1 - drivers/media/dvb/mantis/mantis_vp1034.c | 1 - drivers/media/dvb/mantis/mantis_vp1041.c | 1 - drivers/media/dvb/mantis/mantis_vp2033.c | 1 - drivers/media/dvb/mantis/mantis_vp2040.c | 1 - drivers/media/dvb/mantis/mantis_vp3030.c | 1 - 16 files changed, 3 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c index 01a9ff07d77..6d5d101f0ab 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -190,10 +190,6 @@ static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_dev return err; -fail5: - dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB exit! <%d>", err); - mantis_dvb_exit(mantis); - fail4: dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); mantis_dma_exit(mantis); diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c index 16b39d3b9ac..76cad876338 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.c +++ b/drivers/media/dvb/mantis/hopper_vp3028.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 4151cba35e7..88899ac96d6 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index 638177ce72a..0b52f996f8e 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -197,19 +197,6 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_dev devs++; return err; - -fail7: - dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err); - mantis_uart_exit(mantis); - -fail6: - dprintk(MANTIS_ERROR, 1, "ERROR: Mantis CA exit! <%d>", err); - mantis_ca_exit(mantis); - -fail5: - dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB exit! <%d>", err); - mantis_dvb_exit(mantis); - fail4: dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); mantis_dma_exit(mantis); diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 9d9c5582ada..1e08e310763 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 2005b2489b7..9304b0edd89 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -20,7 +20,6 @@ #include -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index bb05427fdeb..73e5ca0c6c1 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -40,22 +39,6 @@ #include "mantis_reg.h" -static int mantis_hif_data_available(struct mantis_ca *ca) -{ - struct mantis_pci *mantis = ca->ca_priv; - int rc = 0; - - if (wait_event_interruptible_timeout(ca->hif_data_wq, - ca->sbuf_status & MANTIS_SBUF_DATA_AVAIL, - msecs_to_jiffies(500)) == -ERESTARTSYS) { - - dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Read wait event timeout !", mantis->num); - rc = -EREMOTEIO; - } - ca->sbuf_status &= ~MANTIS_SBUF_DATA_AVAIL; - udelay(2); - return rc; -} static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) { diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c index 448e2c3e344..dd6636999ad 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.c +++ b/drivers/media/dvb/mantis/mantis_ioc.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 90ca356985e..d6bca3e5859 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -20,7 +20,6 @@ #include -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c index fb423b0a58f..03b47cf15f8 100644 --- a/drivers/media/dvb/mantis/mantis_uart.c +++ b/drivers/media/dvb/mantis/mantis_uart.c @@ -26,19 +26,18 @@ struct mantis_uart_params { int mantis_uart_read(struct mantis_pci *mantis, u8 *data) { struct mantis_hwconfig *config = mantis->hwconfig; - u32 stat, i; - unsigned long flags; + u32 stat = 0, i; /* get data */ for (i = 0; i < (config->bytes + 1); i++) { + stat = mmread(MANTIS_UART_STAT); + if (stat & MANTIS_UART_RXFIFO_FULL) { dprintk(MANTIS_ERROR, 1, "RX Fifo FULL"); } data[i] = mmread(MANTIS_UART_RXD) & 0x3f; - stat = mmread(MANTIS_UART_STAT); - dprintk(MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f); if (data[i] & (1 << 7)) { diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 0bea6e89f55..c9760b00d0a 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 98a4ec89f04..7ddd149b0fe 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 1181fad3b27..368fc815a61 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index cef108c5ffc..45f71749bb9 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index e2019884ac3..8471bff672f 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index a44fac3aabc..1895e956b16 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include -- cgit v1.2.3-70-g09d2 From 83dbe82bd7766e5045e6561bd44e22b801e7ad76 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 9 Dec 2009 19:00:33 -0300 Subject: V4L/DVB (13803): Remove unused dependency on CU1216 Thanks to Matthias Wachter for pointing it out. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig index aaf025097b4..f9219cd7bb0 100644 --- a/drivers/media/dvb/mantis/Kconfig +++ b/drivers/media/dvb/mantis/Kconfig @@ -11,7 +11,6 @@ config DVB_MANTIS tristate "MANTIS based cards" depends on MANTIS_CORE && DVB_CORE && PCI && I2C select DVB_MB86A16 - select DVB_CU1216 select DVB_ZL10353 select DVB_STV0299 select DVB_PLL -- cgit v1.2.3-70-g09d2 From 0ac6e141eb105f5845eb7066b5279709393b1c78 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 9 Dec 2009 19:27:17 -0300 Subject: V4L/DVB (13804): Remove unused I2C Adapter ID Signed-off-by: Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_i2c.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 9d2b51d2e4b..7bb4e78aa71 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -33,8 +33,6 @@ #include "mantis_reg.h" #include "mantis_i2c.h" -#define I2C_HW_B_MANTIS 0x1c - #define TRIALS 10000 static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) @@ -234,7 +232,6 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) i2c_adapter->class = I2C_CLASS_TV_DIGITAL; i2c_adapter->algo = &mantis_algo; i2c_adapter->algo_data = NULL; - i2c_adapter->id = I2C_HW_B_MANTIS; i2c_adapter->timeout = 500; i2c_adapter->retries = 3; i2c_adapter->dev.parent = &pdev->dev; -- cgit v1.2.3-70-g09d2 From c5e598a6f89ca7335db9f327e24e3abd13d137cf Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 9 Dec 2009 19:59:26 -0300 Subject: V4L/DVB (13805): Fix: Unregister the frontend before detaching Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 1e08e310763..54bf4ea9efd 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -281,8 +281,8 @@ int __devexit mantis_dvb_exit(struct mantis_pci *mantis) err = mantis_frontend_shutdown(mantis); if (err != 0) dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); - dvb_frontend_detach(mantis->fe); dvb_unregister_frontend(mantis->fe); + dvb_frontend_detach(mantis->fe); } tasklet_kill(&mantis->tasklet); -- cgit v1.2.3-70-g09d2 From a1497357dce240880d984f4b657b54245f739dbc Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 11 Dec 2009 20:41:07 -0300 Subject: V4L/DVB (13806): Register and Initialize Remote control Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 3 +- drivers/media/dvb/mantis/mantis_cards.c | 14 +++ drivers/media/dvb/mantis/mantis_common.h | 2 + drivers/media/dvb/mantis/mantis_input.c | 147 +++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_uart.c | 55 +++++++++--- drivers/media/dvb/mantis/mantis_uart.h | 3 +- 6 files changed, 209 insertions(+), 15 deletions(-) create mode 100644 drivers/media/dvb/mantis/mantis_input.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index 399c9018cdb..98dc5cd258a 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -7,7 +7,8 @@ mantis_core-objs := mantis_ioc.o \ mantis_evm.o \ mantis_hif.o \ mantis_ca.o \ - mantis_pcmcia.o + mantis_pcmcia.o \ + mantis_input.o mantis-objs := mantis_cards.o \ mantis_vp1033.o \ diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index 0b52f996f8e..f3fefbbc876 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -194,9 +194,21 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_dev dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err); goto fail4; } + err = mantis_uart_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART initialization failed <%d>", err); + goto fail6; + } + devs++; return err; + + + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err); + mantis_uart_exit(mantis); + +fail6: fail4: dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); mantis_dma_exit(mantis); @@ -222,6 +234,8 @@ static void __devexit mantis_pci_remove(struct pci_dev *pdev) struct mantis_pci *mantis = pci_get_drvdata(pdev); if (mantis) { + + mantis_uart_exit(mantis); mantis_dvb_exit(mantis); mantis_dma_exit(mantis); mantis_i2c_exit(mantis); diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 6ae3aabe560..c2d085460e6 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -170,6 +170,8 @@ struct mantis_pci { wait_queue_head_t uart_wq; struct work_struct uart_work; spinlock_t uart_lock; + + struct input_dev *rc; }; #define MANTIS_HIF_STATUS (mantis->gpio_status) diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c new file mode 100644 index 00000000000..9395fcf4a45 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -0,0 +1,147 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_uart.h" + +static struct ir_scancode mantis_ir_table[] = { + { 0x29, KEY_POWER }, + { 0x28, KEY_FAVORITES }, + { 0x30, KEY_TEXT }, + { 0x17, KEY_INFO }, // Preview + { 0x23, KEY_EPG }, + { 0x3b, KEY_F22 },// Record List + { 0x3c, KEY_1 }, + { 0x3e, KEY_2 }, + { 0x39, KEY_3 }, + { 0x36, KEY_4 }, + { 0x22, KEY_5 }, + { 0x20, KEY_6 }, + { 0x32, KEY_7 }, + { 0x26, KEY_8 }, + { 0x24, KEY_9 }, + { 0x2a, KEY_0 }, + + { 0x33, KEY_CANCEL }, + { 0x2c, KEY_BACK }, + { 0x15, KEY_CLEAR }, + { 0x3f, KEY_TAB }, + { 0x10, KEY_ENTER }, + { 0x14, KEY_UP }, + { 0x0d, KEY_RIGHT }, + { 0x0e, KEY_DOWN }, + { 0x11, KEY_LEFT }, + + { 0x21, KEY_VOLUMEUP }, + { 0x35, KEY_VOLUMEDOWN }, + { 0x3d, KEY_CHANNELDOWN }, + { 0x3a, KEY_CHANNELUP }, + { 0x2e, KEY_RECORD }, + { 0x2b, KEY_PLAY }, + { 0x13, KEY_PAUSE }, + { 0x25, KEY_STOP }, + + { 0x1f, KEY_REWIND }, + { 0x2d, KEY_FASTFORWARD }, + { 0x1e, KEY_PREVIOUS }, // Replay |< + { 0x1d, KEY_NEXT }, // Skip >| + + { 0x0b, KEY_CAMERA }, // Capture + { 0x0f, KEY_LANGUAGE }, // SAP + { 0x18, KEY_MODE }, // PIP + { 0x12, KEY_ZOOM }, // Full screen, + { 0x1c, KEY_SUBTITLE }, + { 0x2f, KEY_MUTE }, + { 0x16, KEY_F20 }, // L/R, + { 0x38, KEY_F21 }, // Hibernate, + + { 0x37, KEY_SWITCHVIDEOMODE }, // A/V + { 0x31, KEY_AGAIN }, // Recall, + { 0x1a, KEY_KPPLUS }, // Zoom+, + { 0x19, KEY_KPMINUS }, // Zoom-, + { 0x27, KEY_RED }, + { 0x0C, KEY_GREEN }, + { 0x01, KEY_YELLOW }, + { 0x00, KEY_BLUE }, +}; + +struct ir_scancode_table ir_mantis = { + .scan = mantis_ir_table, + .size = ARRAY_SIZE(mantis_ir_table), +}; +EXPORT_SYMBOL_GPL(ir_mantis); + +int mantis_input_init(struct mantis_pci *mantis) +{ + struct input_dev *rc; + struct ir_input_state rc_state; + char name[80], dev[80]; + int err; + + rc = input_allocate_device(); + if (!rc) { + dprintk(MANTIS_ERROR, 1, "Input device allocate failed"); + return -ENOMEM; + } + + sprintf(name, "Mantis %s IR receiver", mantis->hwconfig->model_name); + sprintf(dev, "pci-%s/ir0", pci_name(mantis->pdev)); + + rc->name = name; + rc->phys = dev; + + ir_input_init(rc, &rc_state, IR_TYPE_OTHER, &ir_mantis); + + rc->id.bustype = BUS_PCI; + rc->id.vendor = mantis->vendor_id; + rc->id.product = mantis->device_id; + rc->id.version = 1; + rc->dev = mantis->pdev->dev; + + err = input_register_device(rc); + if (err) { + dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); + return -ENODEV; + } + + mantis->rc = rc; + + return 0; +} + +int mantis_exit(struct mantis_pci *mantis) +{ + struct input_dev *rc = mantis->rc; + + input_unregister_device(rc); + + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c index 03b47cf15f8..7d2f2398fa8 100644 --- a/drivers/media/dvb/mantis/mantis_uart.c +++ b/drivers/media/dvb/mantis/mantis_uart.c @@ -1,7 +1,26 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #include #include -#include #include #include #include @@ -21,6 +40,24 @@ struct mantis_uart_params { enum mantis_parity parity; }; +static struct { + char string[7]; +} rates[5] = { + { "9600" }, + { "19200" }, + { "38400" }, + { "57600" }, + { "115200" } +}; + +static struct { + char string[5]; +} parity[3] = { + { "NONE" }, + { "ODD" }, + { "EVEN" } +}; + #define UART_MAX_BUF 16 int mantis_uart_read(struct mantis_pci *mantis, u8 *data) @@ -60,12 +97,10 @@ static void mantis_uart_work(struct work_struct *work) u8 buf[16]; int i; - dprintk(MANTIS_DEBUG, 1, "UART read"); mantis_uart_read(mantis, buf); - dprintk(MANTIS_DEBUG, 1, "UART: "); for (i = 0; i < (config->bytes + 1); i++) - dprintk(MANTIS_DEBUG, 0, "<%02x> ", buf[i]); + dprintk(MANTIS_INFO, 1, "UART BUF:%d <%02x> ", i, buf[i]); dprintk(MANTIS_DEBUG, 0, "\n"); } @@ -73,15 +108,8 @@ static void mantis_uart_work(struct work_struct *work) static int mantis_uart_setup(struct mantis_pci *mantis, struct mantis_uart_params *params) { - char* rates[] = { "B_9600", "B_19200", "B_38400", "B_57600", "B_115200" }; - char* parity[] = { "NONE", "ODD", "EVEN" }; - u32 reg; - dprintk(MANTIS_DEBUG, 1, "Set Parity <%s> Baud Rate <%s>", - parity[params->parity], - rates[params->baud_rate]); - mmwrite((mmread(MANTIS_UART_CTL) | (params->parity & 0x3)), MANTIS_UART_CTL); reg = mmread(MANTIS_UART_BAUD); @@ -116,10 +144,12 @@ int mantis_uart_init(struct mantis_pci *mantis) struct mantis_hwconfig *config = mantis->hwconfig; struct mantis_uart_params params; - dprintk(MANTIS_DEBUG, 1, "Initializing UART .."); /* default parity: */ params.baud_rate = config->baud_rate; params.parity = config->parity; + dprintk(MANTIS_INFO, 1, "Initializing UART @ %sbps parity:%s", + rates[params.baud_rate].string, + parity[params.parity].string); init_waitqueue_head(&mantis->uart_wq); spin_lock_init(&mantis->uart_lock); @@ -142,6 +172,7 @@ int mantis_uart_init(struct mantis_pci *mantis) mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL); schedule_work(&mantis->uart_work); + dprintk(MANTIS_DEBUG, 1, "UART succesfully initialized"); return 0; } diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h index 0a42cd01ab2..62ab66ebb97 100644 --- a/drivers/media/dvb/mantis/mantis_uart.h +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -45,10 +45,9 @@ enum mantis_baud { }; enum mantis_parity { - MANTIS_PARITY_UNDEFINED = 0, + MANTIS_PARITY_NONE = 0, MANTIS_PARITY_EVEN, MANTIS_PARITY_ODD, - MANTIS_PARITY_NONE }; struct mantis_pci; -- cgit v1.2.3-70-g09d2 From 1e42dc78900e9d0ce89d77f3ba6aca00abd5f1b5 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 12 Dec 2009 03:14:25 -0300 Subject: V4L/DVB (13807): Fix: Free device in the device registration failure case Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_input.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index 9395fcf4a45..b27d7759788 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -129,6 +129,7 @@ int mantis_input_init(struct mantis_pci *mantis) err = input_register_device(rc); if (err) { dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); + input_free_device(rc); return -ENODEV; } -- cgit v1.2.3-70-g09d2 From f5ae4f6f482191c531ea9e50ac91d9bd2ffca171 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 08:47:21 -0300 Subject: V4L/DVB (13809): Fix Checkpatch violations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 109 +++++++++++++++-------------- drivers/media/dvb/frontends/mb86a16.h | 2 +- drivers/media/dvb/frontends/mb86a16_priv.h | 2 +- drivers/media/dvb/frontends/tda665x.c | 32 ++++----- drivers/media/dvb/frontends/tda665x.h | 2 +- drivers/media/dvb/mantis/hopper_cards.c | 2 +- drivers/media/dvb/mantis/mantis_ca.c | 4 +- drivers/media/dvb/mantis/mantis_cards.c | 2 +- drivers/media/dvb/mantis/mantis_core.c | 48 ++++++++----- drivers/media/dvb/mantis/mantis_core.h | 14 ++-- drivers/media/dvb/mantis/mantis_dma.c | 11 +-- drivers/media/dvb/mantis/mantis_dvb.c | 12 +--- drivers/media/dvb/mantis/mantis_i2c.c | 2 +- drivers/media/dvb/mantis/mantis_input.c | 28 ++++---- drivers/media/dvb/mantis/mantis_reg.h | 2 +- drivers/media/dvb/mantis/mantis_vp1033.c | 12 ++-- drivers/media/dvb/mantis/mantis_vp1034.c | 2 +- drivers/media/dvb/mantis/mantis_vp1041.c | 9 ++- drivers/media/dvb/mantis/mantis_vp2033.c | 2 +- drivers/media/dvb/mantis/mantis_vp2040.c | 2 +- 20 files changed, 155 insertions(+), 144 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 33387b78d85..32f20c68144 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -37,11 +37,11 @@ struct mb86a16_state { const struct mb86a16_config *config; struct dvb_frontend frontend; - // tuning parameters + /* tuning parameters */ int frequency; int srate; - // Internal stuff + /* Internal stuff */ int master_clk; int deci; int csel; @@ -105,7 +105,7 @@ static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val) .flags = 0, .buf = b0, .len = 1 - },{ + }, { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, @@ -435,7 +435,7 @@ static int signal_det(struct mb86a16_state *state, wait_sym = 80000; } for (i = 0; i < 3; i++) { - if (i == 0 ) + if (i == 0) smrtd = smrt * 98 / 100; else if (i == 1) smrtd = smrt; @@ -480,11 +480,11 @@ static int rf_val_set(struct mb86a16_state *state, unsigned char rf_val[5]; int ack = -1; - if (smrt > 37750 ) + if (smrt > 37750) C = 1; else if (smrt > 18875) C = 2; - else if (smrt > 5500 ) + else if (smrt > 5500) C = 3; else C = 4; @@ -526,7 +526,7 @@ static int rf_val_set(struct mb86a16_state *state, rf_val[2] = (M & 0x00ff0) >> 4; rf_val[3] = ((M & 0x0000f) << 4) | B; - // Frequency Set + /* Frequency Set */ if (mb86a16_write(state, 0x21, rf_val[0]) < 0) ack = 0; if (mb86a16_write(state, 0x22, rf_val[1]) < 0) @@ -655,8 +655,8 @@ static int freqerr_chk(struct mb86a16_state *state, unsigned char CRM, AFCML, AFCMH; unsigned char temp1, temp2, temp3; int crm, afcm, AFCM; - int crrerr, afcerr; // [kHz] - int frqerr; // [MHz] + int crrerr, afcerr; /* kHz */ + int frqerr; /* MHz */ int afcen, afcexen = 0; int R, M, fOSC, fOSC_OFS; @@ -718,12 +718,12 @@ static int freqerr_chk(struct mb86a16_state *state, fOSC_OFS = fOSC - fTP; - if (unit == 0) { //[MHz] + if (unit == 0) { /* MHz */ if (crrerr + afcerr + fOSC_OFS * 1000 >= 0) frqerr = (crrerr + afcerr + fOSC_OFS * 1000 + 500) / 1000; else frqerr = (crrerr + afcerr + fOSC_OFS * 1000 - 500) / 1000; - } else { //[kHz] + } else { /* kHz */ frqerr = crrerr + afcerr + fOSC_OFS * 1000; } @@ -760,13 +760,13 @@ static void swp_info_get(struct mb86a16_state *state, crnt_swp_freq = fOSC_start * 1000 + v * swp_ofs; - if (R == 0 ) + if (R == 0) *fOSC = (crnt_swp_freq + 1000) / 2000 * 2; else *fOSC = (crnt_swp_freq + 500) / 1000; if (*fOSC >= crnt_swp_freq) - *afcex_freq = *fOSC *1000 - crnt_swp_freq; + *afcex_freq = *fOSC * 1000 - crnt_swp_freq; else *afcex_freq = crnt_swp_freq - *fOSC * 1000; @@ -782,7 +782,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V int swp_freq ; if ((i % 2 == 1) && (v <= vmax)) { - // positive v (case 1) + /* positive v (case 1) */ if ((v - 1 == vmin) && (*(V + 30 + v) >= 0) && (*(V + 30 + v - 1) >= 0) && @@ -796,7 +796,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v - 1) >= 0) && (*(V + 30 + v) > *(V + 30 + v - 1)) && (*(V + 30 + v) > SIGMIN)) { - // (case 2) + /* (case 2) */ swp_freq = fOSC * 1000 + afcex_freq; *SIG1 = *(V + 30 + v); } else if ((*(V + 30 + v) > 0) && @@ -807,7 +807,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v - 2) > *(V + 30 + v - 3)) && ((*(V + 30 + v - 1) > SIGMIN) || (*(V + 30 + v - 2) > SIGMIN))) { - // (case 3) + /* (case 3) */ if (*(V + 30 + v - 1) >= *(V + 30 + v - 2)) { swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; *SIG1 = *(V + 30 + v - 1); @@ -823,7 +823,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v - 1) > *(V + 30 + v - 2)) && ((*(V + 30 + v) > SIGMIN) || (*(V + 30 + v - 1) > SIGMIN))) { - // (case 4) + /* (case 4) */ if (*(V + 30 + v) >= *(V + 30 + v - 1)) { swp_freq = fOSC * 1000 + afcex_freq; *SIG1 = *(V + 30 + v); @@ -835,7 +835,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V swp_freq = -1 ; } } else if ((i % 2 == 0) && (v >= vmin)) { - // Negative v (case 1) + /* Negative v (case 1) */ if ((*(V + 30 + v) > 0) && (*(V + 30 + v + 1) > 0) && (*(V + 30 + v + 2) > 0) && @@ -850,7 +850,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v + 1) >= 0) && (*(V + 30 + v + 1) > *(V + 30 + v)) && (*(V + 30 + v + 1) > SIGMIN)) { - // (case 2) + /* (case 2) */ swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; *SIG1 = *(V + 30 + v); } else if ((v == vmin) && @@ -860,18 +860,18 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v) > *(V + 30 + v + 1)) && (*(V + 30 + v) > *(V + 30 + v + 2)) && (*(V + 30 + v) > SIGMIN)) { - // (case 3) + /* (case 3) */ swp_freq = fOSC * 1000 + afcex_freq; *SIG1 = *(V + 30 + v); } else if ((*(V + 30 + v) >= 0) && (*(V + 30 + v + 1) >= 0) && (*(V + 30 + v + 2) >= 0) && - (*(V +30 + v + 3) >= 0) && + (*(V + 30 + v + 3) >= 0) && (*(V + 30 + v + 1) > *(V + 30 + v)) && (*(V + 30 + v + 2) > *(V + 30 + v + 3)) && ((*(V + 30 + v + 1) > SIGMIN) || (*(V + 30 + v + 2) > SIGMIN))) { - // (case 4) + /* (case 4) */ if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; *SIG1 = *(V + 30 + v + 1); @@ -889,7 +889,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v + 1) > *(V + 30 + v + 3)) && ((*(V + 30 + v) > SIGMIN) || (*(V + 30 + v + 1) > SIGMIN))) { - // (case 5) + /* (case 5) */ if (*(V + 30 + v) >= *(V + 30 + v + 1)) { swp_freq = fOSC * 1000 + afcex_freq; *SIG1 = *(V + 30 + v); @@ -905,7 +905,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v + 2) > *(V + 30 + v)) && ((*(V + 30 + v + 1) > SIGMIN) || (*(V + 30 + v + 2) > SIGMIN))) { - // (case 6) + /* (case 6) */ if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; *SIG1 = *(V + 30 + v + 1); @@ -916,8 +916,10 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V } else if ((vmax == 0) && (vmin == 0) && (*(V + 30 + v) > SIGMIN)) { swp_freq = fOSC * 1000; *SIG1 = *(V + 30 + v); - } else swp_freq = -1; - } else swp_freq = -1; + } else + swp_freq = -1; + } else + swp_freq = -1; return swp_freq; } @@ -962,7 +964,7 @@ static void afcex_info_get(struct mb86a16_state *state, static int SEQ_set(struct mb86a16_state *state, unsigned char loop) { - // SLOCK0 = 0 + /* SLOCK0 = 0 */ if (mb86a16_write(state, 0x32, 0x02 | (loop << 2)) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); return -EREMOTEIO; @@ -973,7 +975,7 @@ static int SEQ_set(struct mb86a16_state *state, unsigned char loop) static int iq_vt_set(struct mb86a16_state *state, unsigned char IQINV) { - // Viterbi Rate, IQ Settings + /* Viterbi Rate, IQ Settings */ if (mb86a16_write(state, 0x06, 0xdf | (IQINV << 5)) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); return -EREMOTEIO; @@ -1031,7 +1033,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) unsigned char TIMINT1, TIMINT2, TIMEXT; unsigned char S0T, S1T; unsigned char S2T; -// unsigned char S2T, S3T; +/* unsigned char S2T, S3T; */ unsigned char S4T, S5T; unsigned char AFCEX_L, AFCEX_H; unsigned char R; @@ -1052,7 +1054,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) int temp_freq, delta_freq; int dagcm[4]; int smrt_d; -// int freq_err; +/* int freq_err; */ int n; int ret = -1; int sync; @@ -1093,19 +1095,19 @@ static int mb86a16_set_fe(struct mb86a16_state *state) } if (EN_set(state, CREN, AFCEN) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); - return -1; // (0, 0) + return -1; /* (0, 0) */ } if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); - return -1; // (1, smrt) = (1, symbolrate) + return -1; /* (1, smrt) = (1, symbolrate) */ } if (CNTM_set(state, TIMINT1, TIMINT2, TIMEXT) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "CNTM set error"); - return -1; // (0, 1, 2) + return -1; /* (0, 1, 2) */ } if (S01T_set(state, S1T, S0T) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); - return -1; // (0, 0) + return -1; /* (0, 0) */ } smrt_info_get(state, state->srate); if (smrt_set(state, state->srate) < 0) { @@ -1133,13 +1135,15 @@ static int mb86a16_set_fe(struct mb86a16_state *state) ftemp = ftemp + swp_ofs; vmax++; - // Upper bound + /* Upper bound */ if (ftemp > 2150000) { loop = 0; vmax--; + } else { + if ((ftemp == 2150000) || + (ftemp - state->frequency * 1000 >= fcp + state->srate / 4)) + loop = 0; } - else if ((ftemp == 2150000) || (ftemp - state->frequency * 1000 >= fcp + state->srate / 4)) - loop = 0; } loop = 1; @@ -1149,13 +1153,15 @@ static int mb86a16_set_fe(struct mb86a16_state *state) ftemp = ftemp - swp_ofs; vmin--; - // Lower bound + /* Lower bound */ if (ftemp < 950000) { loop = 0; vmin++; + } else { + if ((ftemp == 950000) || + (state->frequency * 1000 - ftemp >= fcp + state->srate / 4)) + loop = 0; } - else if ((ftemp == 950000) || (state->frequency * 1000 - ftemp >= fcp + state->srate / 4)) - loop = 0; } wait_t = (8000 + state->srate / 2) / state->srate; @@ -1199,7 +1205,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) V[30 + v] = SIG1 ; swp_freq = swp_freq_calcuation(state, i, v, V, vmax, vmin, SIG1MIN, fOSC, afcex_freq, - swp_ofs, &SIG1); //changed + swp_ofs, &SIG1); /* changed */ signal_dupl = 0; for (j = 0; j < prev_freq_num; j++) { @@ -1291,7 +1297,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) dprintk(verbose, MB86A16_ERROR, 1, "srst error"); return -1; } - // delay 4~200 + /* delay 4~200 */ wait_t = 200000 / state->master_clk + 200000 / state->srate; msleep(wait_t); afcerr = afcerr_chk(state); @@ -1452,7 +1458,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2; wait_t = 7 + (2097152 + state->srate / 2) / state->srate; } - wait_t *= 2; /* FOS */ + wait_t *= 2; /* FOS */ S2T_set(state, S2T); S45T_set(state, S4T, S5T); Vi_set(state, ETH, VIA); @@ -1461,13 +1467,14 @@ static int mb86a16_set_fe(struct mb86a16_state *state) sync = sync_chk(state, &VIRM); dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync); if (VIRM) { - if (VIRM == 4) { // 5/6 + if (VIRM == 4) { + /* 5/6 */ if (SIG1 > 110) - wait_t = ( 786432 + state->srate / 2) / state->srate; + wait_t = (786432 + state->srate / 2) / state->srate; else wait_t = (1572864 + state->srate / 2) / state->srate; if (state->srate < 5000) - // FIXME ! , should be a long wait ! + /* FIXME ! , should be a long wait ! */ msleep_interruptible(wait_t); else msleep_interruptible(wait_t); @@ -1477,9 +1484,9 @@ static int mb86a16_set_fe(struct mb86a16_state *state) FEC_srst(state); } } - // 1/2, 2/3, 3/4, 7/8 + /* 1/2, 2/3, 3/4, 7/8 */ if (SIG1 > 110) - wait_t = ( 786432 + state->srate / 2) / state->srate; + wait_t = (786432 + state->srate / 2) / state->srate; else wait_t = (1572864 + state->srate / 2) / state->srate; msleep_interruptible(wait_t); @@ -1491,7 +1498,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) } } } else { - dprintk (verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); + dprintk(verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); ret = -1; } @@ -1846,7 +1853,7 @@ struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, u8 dev_id = 0; struct mb86a16_state *state = NULL; - state = kmalloc(sizeof (struct mb86a16_state), GFP_KERNEL); + state = kmalloc(sizeof(struct mb86a16_state), GFP_KERNEL); if (state == NULL) goto error; @@ -1857,7 +1864,7 @@ struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, if (dev_id != 0xfe) goto error; - memcpy(&state->frontend.ops, &mb86a16_ops, sizeof (struct dvb_frontend_ops)); + memcpy(&state->frontend.ops, &mb86a16_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; state->frontend.ops.set_voltage = state->config->set_voltage; diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb/frontends/mb86a16.h index b7545d0343f..68f25a64017 100644 --- a/drivers/media/dvb/frontends/mb86a16.h +++ b/drivers/media/dvb/frontends/mb86a16.h @@ -35,4 +35,4 @@ extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, struct i2c_adapter *i2c_adap); -#endif //__MB86A16_H +#endif /* __MB86A16_H */ diff --git a/drivers/media/dvb/frontends/mb86a16_priv.h b/drivers/media/dvb/frontends/mb86a16_priv.h index 5de57006806..d8757fafcf1 100644 --- a/drivers/media/dvb/frontends/mb86a16_priv.h +++ b/drivers/media/dvb/frontends/mb86a16_priv.h @@ -148,4 +148,4 @@ #define MB86A16_DISTMON 0x52 #define MB86A16_VERSION 0x7f -#endif //__MB86A16_PRIV_H +#endif /* __MB86A16_PRIV_H */ diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb/frontends/tda665x.c index 0732a2d38e1..87d52739c82 100644 --- a/drivers/media/dvb/frontends/tda665x.c +++ b/drivers/media/dvb/frontends/tda665x.c @@ -45,7 +45,7 @@ static int tda665x_read(struct tda665x_state *state, u8 *buf) return err; exit: - printk("%s: I/O Error err=<%d>\n", __func__, err); + printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err); return err; } @@ -61,7 +61,7 @@ static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length) return err; exit: - printk("%s: I/O Error err=<%d>\n", __func__, err); + printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err); return err; } @@ -79,7 +79,7 @@ static int tda665x_get_state(struct dvb_frontend *fe, case DVBFE_TUNER_BANDWIDTH: break; default: - printk("%s: Unknown parameter (param=%d)\n", __func__, param); + printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param); err = -EINVAL; break; } @@ -100,13 +100,13 @@ static int tda665x_get_status(struct dvb_frontend *fe, u32 *status) goto exit; if ((result >> 6) & 0x01) { - printk("%s: Tuner Phase Locked\n", __func__); + printk(KERN_DEBUG "%s: Tuner Phase Locked\n", __func__); *status = 1; } return err; exit: - printk("%s: I/O Error\n", __func__); + printk(KERN_ERR "%s: I/O Error\n", __func__); return err; } @@ -124,7 +124,7 @@ static int tda665x_set_state(struct dvb_frontend *fe, frequency = tstate->frequency; if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) { - printk("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency); + printk(KERN_ERR "%s: Frequency beyond limits, frequency=%d\n", __func__, frequency); return -EINVAL; } @@ -133,8 +133,8 @@ static int tda665x_set_state(struct dvb_frontend *fe, frequency += config->ref_divider >> 1; frequency /= config->ref_divider; - buf[0] = (u8 ) (frequency & 0x7f00) >> 8; - buf[1] = (u8 ) (frequency & 0x00ff) >> 0; + buf[0] = (u8) (frequency & 0x7f00) >> 8; + buf[1] = (u8) (frequency & 0x00ff) >> 0; buf[2] = 0x80 | 0x40 | 0x02; buf[3] = 0x00; @@ -178,7 +178,7 @@ static int tda665x_set_state(struct dvb_frontend *fe, goto exit; /* sleep for some time */ - printk("%s: Waiting to Phase LOCK\n", __func__); + printk(KERN_DEBUG "%s: Waiting to Phase LOCK\n", __func__); msleep(20); /* check status */ err = tda665x_get_status(fe, &status); @@ -186,19 +186,19 @@ static int tda665x_set_state(struct dvb_frontend *fe, goto exit; if (status == 1) { - printk("%s: Tuner Phase locked: status=%d\n", __func__, status); + printk(KERN_DEBUG "%s: Tuner Phase locked: status=%d\n", __func__, status); state->frequency = frequency; /* cache successful state */ } else { - printk("%s: No Phase lock: status=%d\n", __func__, status); + printk(KERN_ERR "%s: No Phase lock: status=%d\n", __func__, status); } } else { - printk("%s: Unknown parameter (param=%d)\n", __func__, param); + printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param); return -EINVAL; } return 0; exit: - printk("%s: I/O Error\n", __func__); + printk(KERN_ERR "%s: I/O Error\n", __func__); return err; } @@ -226,7 +226,7 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, struct tda665x_state *state = NULL; struct dvb_tuner_info *info; - state = kzalloc(sizeof (struct tda665x_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL); if (state == NULL) goto exit; @@ -237,12 +237,12 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, fe->ops.tuner_ops = tda665x_ops; info = &fe->ops.tuner_ops.info; - memcpy(info->name, config->name, sizeof (config->name)); + memcpy(info->name, config->name, sizeof(config->name)); info->frequency_min = config->frequency_min; info->frequency_max = config->frequency_max; info->frequency_step = config->frequency_offst; - printk("%s: Attaching TDA665x (%s) tuner\n", __func__, info->name); + printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name); return fe; diff --git a/drivers/media/dvb/frontends/tda665x.h b/drivers/media/dvb/frontends/tda665x.h index c0b544d8ef5..ec7927aa75a 100644 --- a/drivers/media/dvb/frontends/tda665x.h +++ b/drivers/media/dvb/frontends/tda665x.h @@ -40,7 +40,7 @@ extern struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, #else static inline struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, - const struct tda665x_config *config, + const struct tda665x_config *config, struct i2c_adapter *i2c) { printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__); diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c index 6d5d101f0ab..ca70149f3dd 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -137,7 +137,7 @@ static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_dev struct mantis_hwconfig *config; int err = 0; - mantis = kzalloc(sizeof (struct mantis_pci), GFP_KERNEL); + mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL); if (mantis == NULL) { printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); err = -ENOMEM; diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 88899ac96d6..2f3ba81eaa0 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -119,7 +119,7 @@ static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) struct mantis_pci *mantis = ca->ca_priv; dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); -// mantis_set_direction(mantis, 1); /* Enable TS through CAM */ +/* mantis_set_direction(mantis, 1); */ /* Enable TS through CAM */ return 0; } @@ -148,7 +148,7 @@ int mantis_ca_init(struct mantis_pci *mantis) int ca_flags = 0, result; dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA"); - ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL); + ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL); if (!ca) { dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting .."); result = -ENOMEM; diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index f3fefbbc876..a4250fad6ac 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -145,7 +145,7 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_dev struct mantis_hwconfig *config; int err = 0; - mantis = kzalloc(sizeof (struct mantis_pci), GFP_KERNEL); + mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL); if (mantis == NULL) { printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); err = -ENOMEM; diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 52b3e9ebfcf..3ddc9ba8440 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -36,14 +36,16 @@ static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) .flags = 0, .buf = data, .len = 1 - },{ + }, { .addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = length }, }; - if ((err = i2c_transfer(&mantis->adapter, msg, 2)) < 0) { + + err = i2c_transfer(&mantis->adapter, msg, 2); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >", err, data[0], data[1]); @@ -65,7 +67,8 @@ static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) .len = length }; - if ((err = i2c_transfer(&mantis->adapter, &msg, 1)) < 0) { + err = i2c_transfer(&mantis->adapter, &msg, 1); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", err, length, data[0], data[1]); @@ -81,7 +84,8 @@ static int get_mac_address(struct mantis_pci *mantis) int err; mantis->mac_address[0] = 0x08; - if ((err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6)) < 0) { + err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); return err; @@ -106,25 +110,25 @@ struct mantis_hwconfig unknown_device = { static void mantis_load_config(struct mantis_pci *mantis) { switch (mantis->subsystem_device) { - case MANTIS_VP_1033_DVB_S: // VP-1033 + case MANTIS_VP_1033_DVB_S: /* VP-1033 */ mantis->hwconfig = &vp1033_mantis_config; break; - case MANTIS_VP_1034_DVB_S: // VP-1034 + case MANTIS_VP_1034_DVB_S: /* VP-1034 */ mantis->hwconfig = &vp1034_mantis_config; break; - case MANTIS_VP_1041_DVB_S2: // VP-1041 + case MANTIS_VP_1041_DVB_S2: /* VP-1041 */ case TECHNISAT_SKYSTAR_HD2: mantis->hwconfig = &vp1041_mantis_config; break; - case MANTIS_VP_2033_DVB_C: // VP-2033 + case MANTIS_VP_2033_DVB_C: /* VP-2033 */ mantis->hwconfig = &vp2033_mantis_config; break; - case MANTIS_VP_2040_DVB_C: // VP-2040 - case TERRATEC_CINERGY_C_PCI: // VP-2040 clone + case MANTIS_VP_2040_DVB_C: /* VP-2040 */ + case TERRATEC_CINERGY_C_PCI: /* VP-2040 clone */ case TECHNISAT_CABLESTAR_HD2: mantis->hwconfig = &vp2040_mantis_config; break; - case MANTIS_VP_3030_DVB_T: // VP-3030 + case MANTIS_VP_3030_DVB_T: /* VP-3030 */ mantis->hwconfig = &vp3030_mantis_config; break; default: @@ -149,23 +153,28 @@ int mantis_core_init(struct mantis_pci *mantis) mantis->pdev->irq, mantis->latency, mantis->mantis_addr, mantis->mantis_mmio); - if ((err = mantis_i2c_init(mantis)) < 0) { + err = mantis_i2c_init(mantis); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed"); return err; } - if ((err = get_mac_address(mantis)) < 0) { + err = get_mac_address(mantis); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed"); return err; } - if ((err = mantis_dma_init(mantis)) < 0) { + err = mantis_dma_init(mantis); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed"); return err; } - if ((err = mantis_dvb_init(mantis)) < 0) { + err = mantis_dvb_init(mantis); + if (err < 0) { dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed"); return err; } - if ((err = mantis_uart_init(mantis)) < 0) { + err = mantis_uart_init(mantis); + if (err < 0) { dprintk(verbose, MANTIS_DEBUG, 1, "Mantis UART init failed"); return err; } @@ -191,7 +200,7 @@ int mantis_core_exit(struct mantis_pci *mantis) return 0; } -// Turn the given bit on or off. +/* Turn the given bit on or off. */ void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) { u32 cur; @@ -207,14 +216,15 @@ void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) udelay(100); } -//direction = 0 , no CI passthrough ; 1 , CI passthrough +/* direction = 0 , no CI passthrough ; 1 , CI passthrough */ void mantis_set_direction(struct mantis_pci *mantis, int direction) { u32 reg; reg = mmread(0x28); dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup"); - if (direction == 0x01) { //to CI + if (direction == 0x01) { + /* to CI */ reg |= 0x04; mmwrite(reg, 0x28); reg &= 0xff - 0x04; diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/dvb/mantis/mantis_core.h index a8093940993..8511b0cebac 100644 --- a/drivers/media/dvb/mantis/mantis_core.h +++ b/drivers/media/dvb/mantis/mantis_core.h @@ -33,15 +33,15 @@ struct vendorname { - __u8 *sub_vendor_name; - __u32 sub_vendor_id; + u8 *sub_vendor_name; + u32 sub_vendor_id; }; struct devicetype { - __u8 *sub_device_name; - __u32 sub_device_id; - __u8 device_type; - __u32 type_flags; + u8 *sub_device_name; + u32 sub_device_id; + u8 device_type; + u32 type_flags; }; @@ -54,4 +54,4 @@ extern int mantis_i2c_exit(struct mantis_pci *mantis); extern int mantis_core_init(struct mantis_pci *mantis); extern int mantis_core_exit(struct mantis_pci *mantis); -#endif //__MANTIS_CORE_H +#endif /* __MANTIS_CORE_H */ diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index eab3645f7ac..adad1f37efd 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -43,10 +43,10 @@ #define RISC_IRQ (0x01 << 24) #define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16)) -#define RISC_FLUSH() mantis->risc_pos = 0 -#define RISC_INSTR(opcode) mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode) +#define RISC_FLUSH() (mantis->risc_pos = 0) +#define RISC_INSTR(opcode) (mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode)) -#define MANTIS_BUF_SIZE 64 * 1024 +#define MANTIS_BUF_SIZE (64 * 1024) #define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4) #define MANTIS_BLOCK_COUNT (1 << 4) #define MANTIS_RISC_SIZE PAGE_SIZE @@ -158,7 +158,8 @@ int mantis_dma_init(struct mantis_pci *mantis) goto err; } - if ((err = mantis_calc_lines(mantis)) < 0) { + err = mantis_calc_lines(mantis); + if (err < 0) { dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed"); goto err; @@ -248,7 +249,7 @@ void mantis_dma_xfer(unsigned long data) dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", mantis->last_block, mantis->finished_block); - (config->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) + (config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter) (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT; } diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 54bf4ea9efd..8982d6fdf6b 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -116,7 +116,6 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) if (mantis->feeds == 1) { dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma"); - printk("mantis start feed & dma\n"); mantis_dma_start(mantis); } @@ -137,7 +136,6 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) mantis->feeds--; if (mantis->feeds == 0) { dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma"); - printk("mantis stop feed and dma\n"); mantis_dma_stop(mantis); } @@ -204,9 +202,9 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) } mantis->fe_mem.source = DMX_MEMORY_FE; - result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx,&mantis->fe_mem); + result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem); if (result < 0) { - dprintk(MANTIS_ERROR, 1,"dvb_dmx_init failed, ERROR=%d", result); + dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); goto err3; } @@ -224,10 +222,6 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!"); goto err5; } else { -// if (mantis->dvb_adapter == NULL) { -// dprintk(MANTIS_ERROR, 1, "DVB adapter "); -// goto err5; -// } if (mantis->fe == NULL) { dprintk(MANTIS_ERROR, 1, "FE "); goto err5; @@ -277,7 +271,7 @@ int __devexit mantis_dvb_exit(struct mantis_pci *mantis) int err; if (mantis->fe) { -// mantis_ca_exit(mantis); + /* mantis_ca_exit(mantis); */ err = mantis_frontend_shutdown(mantis); if (err != 0) dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 7bb4e78aa71..dd38b933353 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -225,7 +225,7 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) init_waitqueue_head(&mantis->i2c_wq); mutex_init(&mantis->i2c_lock); - strncpy(i2c_adapter->name, "Mantis I2C", sizeof (i2c_adapter->name)); + strncpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name)); i2c_set_adapdata(i2c_adapter, mantis); i2c_adapter->owner = THIS_MODULE; diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index b27d7759788..487d149c802 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -36,9 +36,9 @@ static struct ir_scancode mantis_ir_table[] = { { 0x29, KEY_POWER }, { 0x28, KEY_FAVORITES }, { 0x30, KEY_TEXT }, - { 0x17, KEY_INFO }, // Preview + { 0x17, KEY_INFO }, /* Preview */ { 0x23, KEY_EPG }, - { 0x3b, KEY_F22 },// Record List + { 0x3b, KEY_F22 }, /* Record List */ { 0x3c, KEY_1 }, { 0x3e, KEY_2 }, { 0x39, KEY_3 }, @@ -71,22 +71,22 @@ static struct ir_scancode mantis_ir_table[] = { { 0x1f, KEY_REWIND }, { 0x2d, KEY_FASTFORWARD }, - { 0x1e, KEY_PREVIOUS }, // Replay |< - { 0x1d, KEY_NEXT }, // Skip >| + { 0x1e, KEY_PREVIOUS }, /* Replay |< */ + { 0x1d, KEY_NEXT }, /* Skip >| */ - { 0x0b, KEY_CAMERA }, // Capture - { 0x0f, KEY_LANGUAGE }, // SAP - { 0x18, KEY_MODE }, // PIP - { 0x12, KEY_ZOOM }, // Full screen, + { 0x0b, KEY_CAMERA }, /* Capture */ + { 0x0f, KEY_LANGUAGE }, /* SAP */ + { 0x18, KEY_MODE }, /* PIP */ + { 0x12, KEY_ZOOM }, /* Full screen */ { 0x1c, KEY_SUBTITLE }, { 0x2f, KEY_MUTE }, - { 0x16, KEY_F20 }, // L/R, - { 0x38, KEY_F21 }, // Hibernate, + { 0x16, KEY_F20 }, /* L/R */ + { 0x38, KEY_F21 }, /* Hibernate */ - { 0x37, KEY_SWITCHVIDEOMODE }, // A/V - { 0x31, KEY_AGAIN }, // Recall, - { 0x1a, KEY_KPPLUS }, // Zoom+, - { 0x19, KEY_KPMINUS }, // Zoom-, + { 0x37, KEY_SWITCHVIDEOMODE }, /* A/V */ + { 0x31, KEY_AGAIN }, /* Recall */ + { 0x1a, KEY_KPPLUS }, /* Zoom+ */ + { 0x19, KEY_KPMINUS }, /* Zoom- */ { 0x27, KEY_RED }, { 0x0C, KEY_GREEN }, { 0x01, KEY_YELLOW }, diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h index 0072e149a56..c2f572b49fa 100644 --- a/drivers/media/dvb/mantis/mantis_reg.h +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -29,7 +29,7 @@ #define MANTIS_INT_RISCEN (0x01 << 27) #define MANTIS_INT_I2CRACK (0x01 << 26) -//#define MANTIS_INT_GPIF (0xff << 12) +/* #define MANTIS_INT_GPIF (0xff << 12) */ #define MANTIS_INT_PCMCIA7 (0x01 << 19) #define MANTIS_INT_PCMCIA6 (0x01 << 18) diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index c9760b00d0a..3c62be30bbb 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -93,7 +93,7 @@ int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, u32 div; - struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof (buf) }; + struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf)}; div = params->frequency / 250; @@ -140,12 +140,12 @@ int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, aclk = 0xb4; bclk = 0x51; } - stv0299_writereg (fe, 0x13, aclk); - stv0299_writereg (fe, 0x14, bclk); + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); - stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, ratio & 0xf0); return 0; } diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 7ddd149b0fe..36486b53f67 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -62,7 +62,7 @@ int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) dprintk(MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); break; default: - dprintk(MANTIS_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); + dprintk(MANTIS_ERROR, 1, "Invalid = (%d)", (u32) voltage); return -EINVAL; } mmwrite(0x00, MANTIS_GPIF_DOUT); diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 368fc815a61..515346dd31d 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -44,7 +44,7 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { -// 0x0000000b , /* SYSREG */ + /* 0x0000000b, *//* SYSREG */ { STB0899_DEV_ID , 0x30 }, { STB0899_DISCNTRL1 , 0x32 }, { STB0899_DISCNTRL2 , 0x80 }, @@ -55,7 +55,7 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { { STB0899_DISSTATUS , 0x20 }, { STB0899_DISF22 , 0x99 }, { STB0899_DISF22RX , 0xa8 }, - //SYSREG ? + /* SYSREG ? */ { STB0899_ACRPRESC , 0x11 }, { STB0899_ACRDIV1 , 0x0a }, { STB0899_ACRDIV2 , 0x05 }, @@ -323,9 +323,8 @@ static int vp1041_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * vp1041_stb0899_config.demod_address); if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, adapter)) { - if (!lnbp21_attach(mantis->fe, adapter, 0, 0)) { - printk("%s: No LNBP21 found!\n", __func__); - } + if (!lnbp21_attach(mantis->fe, adapter, 0, 0)) + dprintk(MANTIS_ERROR, 1, "No LNBP21 found!"); } } else { return -EREMOTEIO; diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 45f71749bb9..07d468ff5e1 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -71,7 +71,7 @@ static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_fronten struct i2c_adapter *adapter = &mantis->adapter; u8 buf[6]; - struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof (buf) }; + struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)}; int i; #define CU1216_IF 36125000 diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index 8471bff672f..a7ca233e800 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -53,7 +53,7 @@ static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_fronten struct i2c_adapter *adapter = &mantis->adapter; u8 buf[6]; - struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof (buf) }; + struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)}; int i; #define CU1216_IF 36125000 -- cgit v1.2.3-70-g09d2 From 28fddb7cd5b7a12b81c8ec1a358749e60760e741 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 09:01:27 -0300 Subject: V4L/DVB (13810): [MB86A16] Use DVB_* macros Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb/frontends/mb86a16.h index 68f25a64017..a88a6a1febf 100644 --- a/drivers/media/dvb/frontends/mb86a16.h +++ b/drivers/media/dvb/frontends/mb86a16.h @@ -31,8 +31,22 @@ struct mb86a16_config { int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); }; + + +#if defined(CONFIG_DVB_MB86A16) || (defined(CONFIG_DVB_MB86A16_MODULE) && defined(MODULE)) + extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, struct i2c_adapter *i2c_adap); +#else + +static inline struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, + struct i2c_adapter *i2c_adap) +{ + printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__); + return NULL; +} + +#endif /* CONFIG_DVB_MB86A16 */ #endif /* __MB86A16_H */ -- cgit v1.2.3-70-g09d2 From 4cd191fba45ee3cf3035d7e4d3a942979cd9c5e4 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 09:04:59 -0300 Subject: V4L/DVB (13811): [MB86A16] Update Copyright header Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 2 +- drivers/media/dvb/frontends/mb86a16.h | 2 +- drivers/media/dvb/frontends/mb86a16_priv.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 32f20c68144..d05f7500e0c 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1,7 +1,7 @@ /* Fujitsu MB86A16 DVB-S/DSS DC Receiver driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb/frontends/mb86a16.h index a88a6a1febf..6ea8c376394 100644 --- a/drivers/media/dvb/frontends/mb86a16.h +++ b/drivers/media/dvb/frontends/mb86a16.h @@ -1,7 +1,7 @@ /* Fujitsu MB86A16 DVB-S/DSS DC Receiver driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/frontends/mb86a16_priv.h b/drivers/media/dvb/frontends/mb86a16_priv.h index d8757fafcf1..360a35acfe8 100644 --- a/drivers/media/dvb/frontends/mb86a16_priv.h +++ b/drivers/media/dvb/frontends/mb86a16_priv.h @@ -1,7 +1,7 @@ /* Fujitsu MB86A16 DVB-S/DSS DC Receiver driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 -- cgit v1.2.3-70-g09d2 From 8825a0970cef408fb2f1a44e3cb05d6ba41a18db Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 09:13:49 -0300 Subject: V4L/DVB (13812): [Mantis/Hopper] Update Copyright header Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/hopper_cards.c | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/hopper_vp3028.c | 4 ++-- drivers/media/dvb/mantis/hopper_vp3028.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_ca.c | 2 +- drivers/media/dvb/mantis/mantis_ca.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_cards.c | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_common.h | 2 +- drivers/media/dvb/mantis/mantis_core.c | 2 +- drivers/media/dvb/mantis/mantis_core.h | 2 +- drivers/media/dvb/mantis/mantis_dma.c | 2 +- drivers/media/dvb/mantis/mantis_dma.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_dvb.c | 2 +- drivers/media/dvb/mantis/mantis_dvb.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_evm.c | 2 +- drivers/media/dvb/mantis/mantis_hif.c | 2 +- drivers/media/dvb/mantis/mantis_hif.h | 2 +- drivers/media/dvb/mantis/mantis_i2c.c | 2 +- drivers/media/dvb/mantis/mantis_i2c.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_ioc.c | 2 +- drivers/media/dvb/mantis/mantis_ioc.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_link.h | 2 +- drivers/media/dvb/mantis/mantis_pci.c | 2 +- drivers/media/dvb/mantis/mantis_pci.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_pcmcia.c | 2 +- drivers/media/dvb/mantis/mantis_reg.h | 2 +- drivers/media/dvb/mantis/mantis_uart.h | 2 +- drivers/media/dvb/mantis/mantis_vp1033.c | 2 +- drivers/media/dvb/mantis/mantis_vp1033.h | 2 +- drivers/media/dvb/mantis/mantis_vp1034.c | 2 +- drivers/media/dvb/mantis/mantis_vp1034.h | 2 +- drivers/media/dvb/mantis/mantis_vp2033.c | 2 +- drivers/media/dvb/mantis/mantis_vp2033.h | 2 +- drivers/media/dvb/mantis/mantis_vp3028.c | 2 +- drivers/media/dvb/mantis/mantis_vp3028.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_vp3030.c | 2 +- drivers/media/dvb/mantis/mantis_vp3030.h | 2 +- 36 files changed, 227 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c index ca70149f3dd..d073c61e3c0 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -1,3 +1,23 @@ +/* + Hopper PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #include #include #include diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c index 76cad876338..96674c78e86 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.c +++ b/drivers/media/dvb/mantis/hopper_vp3028.c @@ -1,7 +1,7 @@ /* - Mantis VP-3028 driver + Hopper VP-3028 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/hopper_vp3028.h b/drivers/media/dvb/mantis/hopper_vp3028.h index e8a3c2297bb..57239498bc8 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.h +++ b/drivers/media/dvb/mantis/hopper_vp3028.h @@ -1,3 +1,23 @@ +/* + Hopper VP-3028 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_VP3028_H #define __MANTIS_VP3028_H diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 2f3ba81eaa0..403ce043d00 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_ca.h b/drivers/media/dvb/mantis/mantis_ca.h index b7e48ee1fac..dc63e55f7ec 100644 --- a/drivers/media/dvb/mantis/mantis_ca.h +++ b/drivers/media/dvb/mantis/mantis_ca.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_CA_H #define __MANTIS_CA_H diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index a4250fad6ac..16f1708fd3b 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index c2d085460e6..d0b645a483c 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 3ddc9ba8440..8113b23ce44 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/dvb/mantis/mantis_core.h index 8511b0cebac..833ee42e694 100644 --- a/drivers/media/dvb/mantis/mantis_core.h +++ b/drivers/media/dvb/mantis/mantis_core.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index adad1f37efd..46202a4012a 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_dma.h b/drivers/media/dvb/mantis/mantis_dma.h index 4cba8763536..6be00fa8209 100644 --- a/drivers/media/dvb/mantis/mantis_dma.h +++ b/drivers/media/dvb/mantis/mantis_dma.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_DMA_H #define __MANTIS_DMA_H diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 8982d6fdf6b..99d82eec3b0 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -1,6 +1,6 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_dvb.h b/drivers/media/dvb/mantis/mantis_dvb.h index 31ebbb47df3..464199db304 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.h +++ b/drivers/media/dvb/mantis/mantis_dvb.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_DVB_H #define __MANTIS_DVB_H diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 9304b0edd89..a7b369a439d 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 73e5ca0c6c1..7477dac628b 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/dvb/mantis/mantis_hif.h index f960c0aeacc..9094f9ed236 100644 --- a/drivers/media/dvb/mantis/mantis_hif.h +++ b/drivers/media/dvb/mantis/mantis_hif.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index dd38b933353..b7df345fe22 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_i2c.h b/drivers/media/dvb/mantis/mantis_i2c.h index d40da4fa000..1342df2faed 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.h +++ b/drivers/media/dvb/mantis/mantis_i2c.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_I2C_H #define __MANTIS_I2C_H diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c index dd6636999ad..de148ded52d 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.c +++ b/drivers/media/dvb/mantis/mantis_ioc.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_ioc.h b/drivers/media/dvb/mantis/mantis_ioc.h index 20526406723..188fe5a8161 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.h +++ b/drivers/media/dvb/mantis/mantis_ioc.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_IOC_H #define __MANTIS_IOC_H diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index f6030c9fba2..2a814774a00 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 5165a390e07..5e4f57615ad 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_pci.h b/drivers/media/dvb/mantis/mantis_pci.h index 5ce776ffcb3..65f00451908 100644 --- a/drivers/media/dvb/mantis/mantis_pci.h +++ b/drivers/media/dvb/mantis/mantis_pci.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_PCI_H #define __MANTIS_PCI_H diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index d6bca3e5859..5cb545b913f 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h index c2f572b49fa..7761f9dc7fe 100644 --- a/drivers/media/dvb/mantis/mantis_reg.h +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h index 62ab66ebb97..ffb62a0a5a1 100644 --- a/drivers/media/dvb/mantis/mantis_uart.h +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 3c62be30bbb..4a723bda003 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -1,7 +1,7 @@ /* Mantis VP-1033 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/dvb/mantis/mantis_vp1033.h index 2c18d215324..7daaa1bf127 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.h +++ b/drivers/media/dvb/mantis/mantis_vp1033.h @@ -1,7 +1,7 @@ /* Mantis VP-1033 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 36486b53f67..8e6ae558ee5 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -1,7 +1,7 @@ /* Mantis VP-1034 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/dvb/mantis/mantis_vp1034.h index 30269129066..323f38ef8e3 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.h +++ b/drivers/media/dvb/mantis/mantis_vp1034.h @@ -1,7 +1,7 @@ /* Mantis VP-1034 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 07d468ff5e1..10ce81790a8 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -1,7 +1,7 @@ /* Mantis VP-2033 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index e6c5fe80f72..c55242b79d5 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -1,7 +1,7 @@ /* Mantis VP-2033 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_vp3028.c b/drivers/media/dvb/mantis/mantis_vp3028.c index 7f8918c2ce6..4155c838a18 100644 --- a/drivers/media/dvb/mantis/mantis_vp3028.c +++ b/drivers/media/dvb/mantis/mantis_vp3028.c @@ -1,7 +1,7 @@ /* Mantis VP-3028 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_vp3028.h b/drivers/media/dvb/mantis/mantis_vp3028.h index c51628ddf3c..b07be6adc52 100644 --- a/drivers/media/dvb/mantis/mantis_vp3028.h +++ b/drivers/media/dvb/mantis/mantis_vp3028.h @@ -1,3 +1,23 @@ +/* + Mantis VP-3028 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.com) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_VP3028_H #define __MANTIS_VP3028_H diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index 1895e956b16..1f433421495 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -1,7 +1,7 @@ /* Mantis VP-3030 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/dvb/mantis/mantis_vp3030.h index 0a110ba5c1d..5f12c426627 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.h +++ b/drivers/media/dvb/mantis/mantis_vp3030.h @@ -1,7 +1,7 @@ /* Mantis VP-3030 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.com) 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 -- cgit v1.2.3-70-g09d2 From 9c0832e3990b541ea1b8f5d44fe4c204a5e7d396 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 16 Dec 2009 23:57:27 -0200 Subject: V4L/DVB(13808a): mantis: convert it to the new ir-core register/unregister functions Fix a merge conflict between mantis and IR cleanups Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_input.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index 487d149c802..6a9df779441 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -118,7 +118,7 @@ int mantis_input_init(struct mantis_pci *mantis) rc->name = name; rc->phys = dev; - ir_input_init(rc, &rc_state, IR_TYPE_OTHER, &ir_mantis); + ir_input_init(rc, &rc_state, IR_TYPE_OTHER); rc->id.bustype = BUS_PCI; rc->id.vendor = mantis->vendor_id; @@ -126,7 +126,7 @@ int mantis_input_init(struct mantis_pci *mantis) rc->id.version = 1; rc->dev = mantis->pdev->dev; - err = input_register_device(rc); + err = ir_input_register(rc, &ir_mantis); if (err) { dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); input_free_device(rc); @@ -142,7 +142,7 @@ int mantis_exit(struct mantis_pci *mantis) { struct input_dev *rc = mantis->rc; - input_unregister_device(rc); + ir_input_unregister(rc); return 0; } -- cgit v1.2.3-70-g09d2 From 8873c61f1fe849bc8719839ddfa3300266f8bc39 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 5 Dec 2009 01:24:08 -0300 Subject: V4L/DVB (13808): [Mantis/Hopper] Build update for Mantis/Hopper based cards Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/Kconfig | 4 ++++ drivers/media/dvb/Makefile | 14 +++++++++++++- drivers/media/dvb/frontends/Kconfig | 8 ++++++++ drivers/media/dvb/frontends/Makefile | 1 + 4 files changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 35d0817126e..cf8f65f309d 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig @@ -72,6 +72,10 @@ comment "Supported Earthsoft PT1 Adapters" depends on DVB_CORE && PCI && I2C source "drivers/media/dvb/pt1/Kconfig" +comment "Supported Mantis Adapters" + depends on DVB_CORE && PCI && I2C + source "drivers/media/dvb/mantis/Kconfig" + comment "Supported DVB Frontends" depends on DVB_CORE source "drivers/media/dvb/frontends/Kconfig" diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index 16d262ddb45..c12922c3659 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile @@ -2,6 +2,18 @@ # Makefile for the kernel multimedia device drivers. # -obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ pt1/ +obj-y := dvb-core/ \ + frontends/ \ + ttpci/ \ + ttusb-dec/ \ + ttusb-budget/ \ + b2c2/ \ + bt8xx/ \ + dvb-usb/ \ + pluto2/ \ + siano/ \ + dm1105/ \ + pt1/ \ + mantis/ obj-$(CONFIG_DVB_FIREDTV) += firewire/ diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 7820ca084b1..cd7f9b7cbff 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -208,6 +208,14 @@ config DVB_DS3000 help A DVB-S/S2 tuner module. Say Y when you want to support this frontend. +config DVB_MB86A16 + tristate "Fujitsu MB86A16 based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S/DSS Direct Conversion reveiver. + Say Y when you want to support this frontend. + comment "DVB-T (terrestrial) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 59f7b880355..874e8ada4d1 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -81,3 +81,4 @@ obj-$(CONFIG_DVB_STV6110x) += stv6110x.o obj-$(CONFIG_DVB_ISL6423) += isl6423.o obj-$(CONFIG_DVB_EC100) += ec100.o obj-$(CONFIG_DVB_DS3000) += ds3000.o +obj-$(CONFIG_DVB_MB86A16) += mb86a16.o -- cgit v1.2.3-70-g09d2 From 184ac7535ee078a4572b668a348134d67c3977d2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Dec 2009 00:06:04 -0200 Subject: V4L/DVB (13808b): mantis: replace DMA_nnBIT_MASK to DMA_BIT_MASK(32) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb/mantis/mantis_pci.c: In function ‘mantis_pci_init’: drivers/media/dvb/mantis/mantis_pci.c:76: warning: ‘DMA_nnBIT_MASK’ is deprecated Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 5e4f57615ad..e7cd8aabd88 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -73,7 +73,7 @@ int __devinit mantis_pci_init(struct mantis_pci *mantis) goto fail0; } - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); if (err != 0) { dprintk(MANTIS_ERROR, 1, "ERROR: Unable to obtain 32 bit DMA <%i>", err); ret = -ENOMEM; -- cgit v1.2.3-70-g09d2 From 4cf0b3f130a4fe573077e4d0237fd3dd0f67d3f6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 18 Dec 2009 09:58:46 -0200 Subject: V4L/DVB(13824a): mantis: Fix __devexit bad annotations WARNING: drivers/media/dvb/mantis/built-in.o(.devinit.text+0x13d7): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/mantis/built-in.o(.devinit.text+0x1433): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/mantis/built-in.o(.devinit.text+0x185e): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/mantis/built-in.o(.devinit.text+0x18ba): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/built-in.o(.devinit.text+0x68b8): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/built-in.o(.devinit.text+0x6914): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/built-in.o(.devinit.text+0x6d3f): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/built-in.o(.devinit.text+0x6d9b): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. WARNING: drivers/media/built-in.o(.devinit.text+0x14634): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/built-in.o(.devinit.text+0x14690): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. WARNING: drivers/media/built-in.o(.devinit.text+0x14abb): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/built-in.o(.devinit.text+0x14b17): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. Acked-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_i2c.c | 2 +- drivers/media/dvb/mantis/mantis_pci.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index b7df345fe22..7870bcf9689 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -253,7 +253,7 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) } EXPORT_SYMBOL_GPL(mantis_i2c_init); -int __devexit mantis_i2c_exit(struct mantis_pci *mantis) +int mantis_i2c_exit(struct mantis_pci *mantis) { u32 intmask; diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index e7cd8aabd88..6c7534af6b4 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -155,7 +155,7 @@ fail0: } EXPORT_SYMBOL_GPL(mantis_pci_init); -void __devexit mantis_pci_exit(struct mantis_pci *mantis) +void mantis_pci_exit(struct mantis_pci *mantis) { struct pci_dev *pdev = mantis->pdev; -- cgit v1.2.3-70-g09d2 From fcd89de3bd1c8735f9b7c759dc4848ab6e525bb9 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 19 Dec 2009 14:11:50 -0300 Subject: V4L/DVB (13851): Fix Input dependency for Mantis > > > > CONFIG_INPUT=n As reported by Randy Dunlap : > ERROR: "ir_input_register" [drivers/media/dvb/mantis/mantis_core.ko] undefined! > ERROR: "ir_input_unregister" [drivers/media/dvb/mantis/mantis_core.ko] undefined! > ERROR: "ir_input_init" [drivers/media/dvb/mantis/mantis_core.ko] undefined! > ERROR: "input_free_device" [drivers/media/dvb/mantis/mantis_core.ko] undefined! > ERROR: "input_allocate_device" [drivers/media/dvb/mantis/mantis_core.ko] undefined! Signed-off-by: Manu Abraham Acked-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig index f9219cd7bb0..f7b72a32adf 100644 --- a/drivers/media/dvb/mantis/Kconfig +++ b/drivers/media/dvb/mantis/Kconfig @@ -1,6 +1,6 @@ config MANTIS_CORE tristate "Mantis/Hopper PCI bridge based devices" - depends on PCI && I2C + depends on PCI && I2C && INPUT help Support for PCI cards based on the Mantis and Hopper PCi bridge. -- cgit v1.2.3-70-g09d2 From ba59953d281747b1f7518a60f0ba8ff671cd0d65 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 15 Jan 2010 12:08:57 +1000 Subject: drm/nouveau: fix a race condition in nouveau_dma_wait() Can be triggered easily on certain cards (NV46 and NV50 of mine) by running "dmesg", the DRM's channel will lockup. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_dma.c | 76 ++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index 7afbe8b40d5..50d9e67745a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -126,47 +126,52 @@ OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) chan->dma.cur += nr_dwords; } -static inline bool -READ_GET(struct nouveau_channel *chan, uint32_t *get) +/* Fetch and adjust GPU GET pointer + * + * Returns: + * value >= 0, the adjusted GET pointer + * -EINVAL if GET pointer currently outside main push buffer + * -EBUSY if timeout exceeded + */ +static inline int +READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout) { uint32_t val; val = nvchan_rd32(chan, chan->user_get); - if (val < chan->pushbuf_base || - val > chan->pushbuf_base + (chan->dma.max << 2)) { - /* meaningless to dma_wait() except to know whether the - * GPU has stalled or not - */ - *get = val; - return false; + + /* reset counter as long as GET is still advancing, this is + * to avoid misdetecting a GPU lockup if the GPU happens to + * just be processing an operation that takes a long time + */ + if (val != *prev_get) { + *prev_get = val; + *timeout = 0; + } + + if ((++*timeout & 0xff) == 0) { + DRM_UDELAY(1); + if (*timeout > 100000) + return -EBUSY; } - *get = (val - chan->pushbuf_base) >> 2; - return true; + if (val < chan->pushbuf_base || + val > chan->pushbuf_base + (chan->dma.max << 2)) + return -EINVAL; + + return (val - chan->pushbuf_base) >> 2; } int nouveau_dma_wait(struct nouveau_channel *chan, int size) { - uint32_t get, prev_get = 0, cnt = 0; - bool get_valid; + uint32_t prev_get = 0, cnt = 0; + int get; while (chan->dma.free < size) { - /* reset counter as long as GET is still advancing, this is - * to avoid misdetecting a GPU lockup if the GPU happens to - * just be processing an operation that takes a long time - */ - get_valid = READ_GET(chan, &get); - if (get != prev_get) { - prev_get = get; - cnt = 0; - } - - if ((++cnt & 0xff) == 0) { - DRM_UDELAY(1); - if (cnt > 100000) - return -EBUSY; - } + get = READ_GET(chan, &prev_get, &cnt); + if (unlikely(get == -EBUSY)) + return -EBUSY; /* loop until we have a usable GET pointer. the value * we read from the GPU may be outside the main ring if @@ -177,7 +182,7 @@ nouveau_dma_wait(struct nouveau_channel *chan, int size) * from the SKIPS area, so the code below doesn't have to deal * with some fun corner cases. */ - if (!get_valid || get < NOUVEAU_DMA_SKIPS) + if (unlikely(get == -EINVAL) || get < NOUVEAU_DMA_SKIPS) continue; if (get <= chan->dma.cur) { @@ -203,6 +208,19 @@ nouveau_dma_wait(struct nouveau_channel *chan, int size) * after processing the currently pending commands. */ OUT_RING(chan, chan->pushbuf_base | 0x20000000); + + /* wait for GET to depart from the skips area. + * prevents writing GET==PUT and causing a race + * condition that causes us to think the GPU is + * idle when it's not. + */ + do { + get = READ_GET(chan, &prev_get, &cnt); + if (unlikely(get == -EBUSY)) + return -EBUSY; + if (unlikely(get == -EINVAL)) + continue; + } while (get <= NOUVEAU_DMA_SKIPS); WRITE_PUT(NOUVEAU_DMA_SKIPS); /* we're now submitting commands at the start of -- cgit v1.2.3-70-g09d2 From 0d92971dd6973d865a873c24df2d7bfe06ec4486 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 15 Jan 2010 12:21:37 +1000 Subject: drm/nouveau: fix thinko in nv04_instmem.c Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv04_instmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c index a20c206625a..a3b9563a6f6 100644 --- a/drivers/gpu/drm/nouveau/nv04_instmem.c +++ b/drivers/gpu/drm/nouveau/nv04_instmem.c @@ -30,7 +30,7 @@ nv04_instmem_determine_amount(struct drm_device *dev) * of vram. For now, only reserve a small piece until we know * more about what each chipset requires. */ - switch (dev_priv->chipset & 0xf0) { + switch (dev_priv->chipset) { case 0x40: case 0x47: case 0x49: -- cgit v1.2.3-70-g09d2 From d051bbb22e9d8e87e2a5b8efb176d1bfd0f7feee Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Sat, 16 Jan 2010 15:27:51 +0100 Subject: drm/nouveau: Acknowledge DMA_VTX_PROTECTION PGRAPH interrupts Currently Nouveau is unable to dismiss DMA_VTX_PROTECTION errors, which results in an infinite loop in the interrupt handler. These errors are caused both by bugs in the Gallium driver and by user-specified index buffers with out of bounds indices. By mmio-tracing the nVidia drivers, I found out how this is done. On DMA_VTX_PROTECTION, The nVidia driver reads the register 0x402000, always getting the value 4, and then writes 4 back to 0x402000. This patch adds that logic by reading 0x402000 and writing the same value back. It's unclear what should happen if the value read is not 4, and the current approach might not be the correct one. To test this, modify mesa/progs/trivial/vbo-drawrange.c, defining ELTOBJ to 1 and replacing indices with huge out of bounds integers. Without this patch, the GPU and/or kernel should lock up. With this patch, it should misrender as expected but not lock up. The errors are still logged since they are useful for development. This has been tested on NV49 and may not work on other cards. To find out how things work on other cards, run the aforementioned test using the blob with mmiotrace and grep for a read of the PGRAPH source register. Signed-off-by: Luca Barbieri Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_irq.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 919a619ca7f..3b9bad66162 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -483,6 +483,13 @@ nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource) if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { if (nouveau_pgraph_intr_swmthd(dev, &trap)) unhandled = 1; + } else if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { + uint32_t v = nv_rd32(dev, 0x402000); + nv_wr32(dev, 0x402000, v); + + /* dump the error anyway for now: it's useful for + Gallium development */ + unhandled = 1; } else { unhandled = 1; } -- cgit v1.2.3-70-g09d2 From 71666475018a3024fb49499096d26a9350349e8b Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Sat, 16 Jan 2010 15:30:15 +0100 Subject: drm/nouveau: Evict buffers in VRAM before freeing sgdma Currently, we take down the sgdma engine without evicting all buffers from VRAM. The TTM device release will try to evict anything in VRAM to GART memory, but this will fail since sgdma has already been taken down. This causes an infinite loop in kernel mode on module unload. It usually doesn't happen because there aren't any buffer on close. However, if the GPU is locked up, this condition is easily triggered. This patch fixes it in the simplest way possible by cleaning VRAM right before cleaning SGDMA memory. Signed-off-by: Luca Barbieri Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_mem.c | 1 - drivers/gpu/drm/nouveau/nouveau_state.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 186f34b01f2..8f3a12f614e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -386,7 +386,6 @@ void nouveau_mem_close(struct drm_device *dev) nouveau_bo_unpin(dev_priv->vga_ram); nouveau_bo_ref(NULL, &dev_priv->vga_ram); - ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); ttm_bo_device_release(&dev_priv->ttm.bdev); nouveau_ttm_global_release(dev_priv); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 09b9a46dfc0..f2d0187ba15 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -525,6 +525,7 @@ static void nouveau_card_takedown(struct drm_device *dev) engine->mc.takedown(dev); mutex_lock(&dev->struct_mutex); + ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); mutex_unlock(&dev->struct_mutex); nouveau_sgdma_takedown(dev); -- cgit v1.2.3-70-g09d2 From 134f248bea4bf5c3169b4950eb49c6651b09eb0e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 18 Jan 2010 08:33:04 +1000 Subject: drm/nv50: fix alignment of per-channel fifo cache GPU pointer to the structure is shifted right by 10 bits, so we need to align to 1024 bytes, not 256. Reported-by: Maarten Maathuis Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_fifo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index 39caf167587..32b244bcb48 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c @@ -272,7 +272,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) return ret; ramfc = chan->ramfc->gpuobj; - ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 256, + ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 1024, 0, &chan->cache); if (ret) return ret; -- cgit v1.2.3-70-g09d2 From 58d65b84dee524b0a4a8b747b8eb8bbf2fb16d9d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 18 Jan 2010 08:52:35 +1000 Subject: drm/nv50: prevent accidently turning off encoders we're actually using On most cards the DisplayPort connector is created with 2 encoders sharing a single SOR (for native DP, and for DVI-over-DP). The previous logic for turning off unused encoders didn't take into account that we could have multiple drm_encoders on a single hw encoder and ended up turning off encoders that were actually being used still. This patch fixes that issue. We probably want to look at something a bit better later on, and only expose one drm_encoder per hw encoder block. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_crtc.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 118d3285fd8..40b7360841f 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -432,6 +432,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc) struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_encoder *encoder; + uint32_t dac = 0, sor = 0; NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); @@ -439,9 +440,28 @@ nv50_crtc_prepare(struct drm_crtc *crtc) list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - if (drm_helper_encoder_in_use(encoder)) + if (!drm_helper_encoder_in_use(encoder)) continue; + if (nv_encoder->dcb->type == OUTPUT_ANALOG || + nv_encoder->dcb->type == OUTPUT_TV) + dac |= (1 << nv_encoder->or); + else + sor |= (1 << nv_encoder->or); + } + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + if (nv_encoder->dcb->type == OUTPUT_ANALOG || + nv_encoder->dcb->type == OUTPUT_TV) { + if (dac & (1 << nv_encoder->or)) + continue; + } else { + if (sor & (1 << nv_encoder->or)) + continue; + } + nv_encoder->disconnect(nv_encoder); } -- cgit v1.2.3-70-g09d2 From 6f2af72a2451b7491fba820b1d1b0b91c6a84027 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 5 Jan 2010 13:59:06 +0000 Subject: mfd: WM8350 off by one bug If irq == WM8350_NUM_IRQ that would put us past the end of the array. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8350-irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c index c8df547c474..9025f29e270 100644 --- a/drivers/mfd/wm8350-irq.c +++ b/drivers/mfd/wm8350-irq.c @@ -434,7 +434,7 @@ int wm8350_register_irq(struct wm8350 *wm8350, int irq, irq_handler_t handler, unsigned long flags, const char *name, void *data) { - if (irq < 0 || irq > WM8350_NUM_IRQ || !handler) + if (irq < 0 || irq >= WM8350_NUM_IRQ || !handler) return -EINVAL; if (wm8350->irq[irq].handler) @@ -453,7 +453,7 @@ EXPORT_SYMBOL_GPL(wm8350_register_irq); int wm8350_free_irq(struct wm8350 *wm8350, int irq) { - if (irq < 0 || irq > WM8350_NUM_IRQ) + if (irq < 0 || irq >= WM8350_NUM_IRQ) return -EINVAL; wm8350_mask_irq(wm8350, irq); -- cgit v1.2.3-70-g09d2 From 64e8867ba8098b69889c1af94997a5ba2348fb26 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Wed, 6 Jan 2010 13:51:48 +0100 Subject: mfd: tmio_mmc hardware abstraction for CNF area This patch abstracts out the CNF area code from tmio_mmc which is not present in all hardware that can use this driver. This is required so that we can support non-toshiba based hardware. ASIC3 support by Philipp Zabel Signed-off-by: Ian Molton Signed-off-by: Magnus Damm Signed-off-by: Samuel Ortiz --- drivers/mfd/Makefile | 6 +-- drivers/mfd/asic3.c | 40 ++++++++++++--- drivers/mfd/t7l66xb.c | 55 +++++++++++++------- drivers/mfd/tc6387xb.c | 119 ++++++++++++++++++++++++++++++++------------ drivers/mfd/tc6393xb.c | 56 +++++++++++++++++---- drivers/mfd/tmio_core.c | 52 +++++++++++++++++++ drivers/mmc/host/tmio_mmc.c | 59 +++++++--------------- drivers/mmc/host/tmio_mmc.h | 46 +++-------------- include/linux/mfd/tmio.h | 39 +++++++++++++++ 9 files changed, 323 insertions(+), 149 deletions(-) create mode 100644 drivers/mfd/tmio_core.c (limited to 'drivers') diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index ca2f2c4ff05..8f0d18409ed 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -11,9 +11,9 @@ obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o -obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o -obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o -obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o +obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o +obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o +obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o obj-$(CONFIG_MFD_WM8400) += wm8400-core.o wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index e22128c3e9a..95c1e6bd172 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -80,6 +80,7 @@ struct asic3 { u16 irq_bothedge[4]; struct gpio_chip gpio; struct device *dev; + void __iomem *tmio_cnf; struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)]; }; @@ -685,8 +686,24 @@ static struct mfd_cell asic3_cell_ds1wm = { .resources = ds1wm_resources, }; +static void asic3_mmc_pwr(struct platform_device *pdev, int state) +{ + struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); + + tmio_core_mmc_pwr(asic->tmio_cnf, 1 - asic->bus_shift, state); +} + +static void asic3_mmc_clk_div(struct platform_device *pdev, int state) +{ + struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); + + tmio_core_mmc_clk_div(asic->tmio_cnf, 1 - asic->bus_shift, state); +} + static struct tmio_mmc_data asic3_mmc_data = { - .hclk = 24576000, + .hclk = 24576000, + .set_pwr = asic3_mmc_pwr, + .set_clk_div = asic3_mmc_clk_div, }; static struct resource asic3_mmc_resources[] = { @@ -695,11 +712,6 @@ static struct resource asic3_mmc_resources[] = { .end = ASIC3_SD_CTRL_BASE + 0x3ff, .flags = IORESOURCE_MEM, }, - { - .start = ASIC3_SD_CONFIG_BASE, - .end = ASIC3_SD_CONFIG_BASE + 0x1ff, - .flags = IORESOURCE_MEM, - }, { .start = 0, .end = 0, @@ -743,6 +755,10 @@ static int asic3_mmc_enable(struct platform_device *pdev) asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF), ASIC3_SDHWCTRL_SDPWR, 1); + /* ASIC3_SD_CTRL_BASE assumes 32-bit addressing, TMIO is 16-bit */ + tmio_core_mmc_enable(asic->tmio_cnf, 1 - asic->bus_shift, + ASIC3_SD_CTRL_BASE >> 1); + return 0; } @@ -797,10 +813,15 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm); /* MMC */ + asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) + + mem_sdio->start, 0x400 >> asic->bus_shift); + if (!asic->tmio_cnf) { + ret = -ENOMEM; + dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n"); + goto out; + } asic3_mmc_resources[0].start >>= asic->bus_shift; asic3_mmc_resources[0].end >>= asic->bus_shift; - asic3_mmc_resources[1].start >>= asic->bus_shift; - asic3_mmc_resources[1].end >>= asic->bus_shift; asic3_cell_mmc.platform_data = &asic3_cell_mmc; asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc); @@ -820,7 +841,10 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, static void asic3_mfd_remove(struct platform_device *pdev) { + struct asic3 *asic = platform_get_drvdata(pdev); + mfd_remove_devices(&pdev->dev); + iounmap(asic->tmio_cnf); } /* Core */ diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 0a255c1f1ce..bcf4687d4af 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c @@ -38,6 +38,19 @@ enum { T7L66XB_CELL_MMC, }; +static const struct resource t7l66xb_mmc_resources[] = { + { + .start = 0x800, + .end = 0x9ff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_T7L66XB_MMC, + .end = IRQ_T7L66XB_MMC, + .flags = IORESOURCE_IRQ, + }, +}; + #define SCR_REVID 0x08 /* b Revision ID */ #define SCR_IMR 0x42 /* b Interrupt Mask */ #define SCR_DEV_CTL 0xe0 /* b Device control */ @@ -83,6 +96,9 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc) spin_unlock_irqrestore(&t7l66xb->lock, flags); + tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0, + t7l66xb_mmc_resources[0].start & 0xfffe); + return 0; } @@ -106,28 +122,28 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc) return 0; } +static void t7l66xb_mmc_pwr(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct t7l66xb *t7l66xb = platform_get_drvdata(dev); + + tmio_core_mmc_pwr(t7l66xb->scr + 0x200, 0, state); +} + +static void t7l66xb_mmc_clk_div(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct t7l66xb *t7l66xb = platform_get_drvdata(dev); + + tmio_core_mmc_clk_div(t7l66xb->scr + 0x200, 0, state); +} + /*--------------------------------------------------------------------------*/ static struct tmio_mmc_data t7166xb_mmc_data = { .hclk = 24000000, -}; - -static const struct resource t7l66xb_mmc_resources[] = { - { - .start = 0x800, - .end = 0x9ff, - .flags = IORESOURCE_MEM, - }, - { - .start = 0x200, - .end = 0x2ff, - .flags = IORESOURCE_MEM, - }, - { - .start = IRQ_T7L66XB_MMC, - .end = IRQ_T7L66XB_MMC, - .flags = IORESOURCE_IRQ, - }, + .set_pwr = t7l66xb_mmc_pwr, + .set_clk_div = t7l66xb_mmc_clk_div, }; static const struct resource t7l66xb_nand_resources[] = { @@ -282,6 +298,9 @@ static int t7l66xb_resume(struct platform_device *dev) if (pdata && pdata->resume) pdata->resume(dev); + tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0, + t7l66xb_mmc_resources[0].start & 0xfffe); + return 0; } #else diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index 3280ab33f88..5c7f04343d5 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c @@ -22,28 +22,52 @@ enum { TC6387XB_CELL_MMC, }; +struct tc6387xb { + void __iomem *scr; + struct clk *clk32k; + struct resource rscr; +}; + +static struct resource tc6387xb_mmc_resources[] = { + { + .start = 0x800, + .end = 0x9ff, + .flags = IORESOURCE_MEM, + }, + { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ, + }, +}; + +/*--------------------------------------------------------------------------*/ + #ifdef CONFIG_PM static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state) { - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); struct tc6387xb_platform_data *pdata = dev->dev.platform_data; if (pdata && pdata->suspend) pdata->suspend(dev); - clk_disable(clk32k); + clk_disable(tc6387xb->clk32k); return 0; } static int tc6387xb_resume(struct platform_device *dev) { - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); struct tc6387xb_platform_data *pdata = dev->dev.platform_data; - clk_enable(clk32k); + clk_enable(tc6387xb->clk32k); if (pdata && pdata->resume) pdata->resume(dev); + tmio_core_mmc_resume(tc6387xb->scr + 0x200, 0, + tc6387xb_mmc_resources[0].start & 0xfffe); + return 0; } #else @@ -53,12 +77,32 @@ static int tc6387xb_resume(struct platform_device *dev) /*--------------------------------------------------------------------------*/ +static void tc6387xb_mmc_pwr(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); + + tmio_core_mmc_pwr(tc6387xb->scr + 0x200, 0, state); +} + +static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); + + tmio_core_mmc_clk_div(tc6387xb->scr + 0x200, 0, state); +} + + static int tc6387xb_mmc_enable(struct platform_device *mmc) { struct platform_device *dev = to_platform_device(mmc->dev.parent); - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); - clk_enable(clk32k); + clk_enable(tc6387xb->clk32k); + + tmio_core_mmc_enable(tc6387xb->scr + 0x200, 0, + tc6387xb_mmc_resources[0].start & 0xfffe); return 0; } @@ -66,36 +110,20 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc) static int tc6387xb_mmc_disable(struct platform_device *mmc) { struct platform_device *dev = to_platform_device(mmc->dev.parent); - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); - clk_disable(clk32k); + clk_disable(tc6387xb->clk32k); return 0; } -/*--------------------------------------------------------------------------*/ - static struct tmio_mmc_data tc6387xb_mmc_data = { .hclk = 24000000, + .set_pwr = tc6387xb_mmc_pwr, + .set_clk_div = tc6387xb_mmc_clk_div, }; -static struct resource tc6387xb_mmc_resources[] = { - { - .start = 0x800, - .end = 0x9ff, - .flags = IORESOURCE_MEM, - }, - { - .start = 0x200, - .end = 0x2ff, - .flags = IORESOURCE_MEM, - }, - { - .start = 0, - .end = 0, - .flags = IORESOURCE_IRQ, - }, -}; +/*--------------------------------------------------------------------------*/ static struct mfd_cell tc6387xb_cells[] = { [TC6387XB_CELL_MMC] = { @@ -111,8 +139,9 @@ static struct mfd_cell tc6387xb_cells[] = { static int tc6387xb_probe(struct platform_device *dev) { struct tc6387xb_platform_data *pdata = dev->dev.platform_data; - struct resource *iomem; + struct resource *iomem, *rscr; struct clk *clk32k; + struct tc6387xb *tc6387xb; int irq, ret; iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); @@ -120,18 +149,40 @@ static int tc6387xb_probe(struct platform_device *dev) return -EINVAL; } + tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL); + if (!tc6387xb) + return -ENOMEM; + ret = platform_get_irq(dev, 0); if (ret >= 0) irq = ret; else - goto err_resource; + goto err_no_irq; clk32k = clk_get(&dev->dev, "CLK_CK32K"); if (IS_ERR(clk32k)) { ret = PTR_ERR(clk32k); + goto err_no_clk; + } + + rscr = &tc6387xb->rscr; + rscr->name = "tc6387xb-core"; + rscr->start = iomem->start; + rscr->end = iomem->start + 0xff; + rscr->flags = IORESOURCE_MEM; + + ret = request_resource(iomem, rscr); + if (ret) goto err_resource; + + tc6387xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1); + if (!tc6387xb->scr) { + ret = -ENOMEM; + goto err_ioremap; } - platform_set_drvdata(dev, clk32k); + + tc6387xb->clk32k = clk32k; + platform_set_drvdata(dev, tc6387xb); if (pdata && pdata->enable) pdata->enable(dev); @@ -149,8 +200,13 @@ static int tc6387xb_probe(struct platform_device *dev) if (!ret) return 0; - clk_put(clk32k); +err_ioremap: + release_resource(&tc6387xb->rscr); err_resource: + clk_put(clk32k); +err_no_clk: +err_no_irq: + kfree(tc6387xb); return ret; } @@ -195,3 +251,4 @@ MODULE_DESCRIPTION("Toshiba TC6387XB core driver"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Ian Molton"); MODULE_ALIAS("platform:tc6387xb"); + diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 1429a7341a9..4bc5a08a2b0 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -136,10 +136,6 @@ static int tc6393xb_nand_enable(struct platform_device *nand) return 0; } -static struct tmio_mmc_data tc6393xb_mmc_data = { - .hclk = 24000000, -}; - static struct resource __devinitdata tc6393xb_nand_resources[] = { { .start = 0x1000, @@ -164,11 +160,6 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = { .end = 0x9ff, .flags = IORESOURCE_MEM, }, - { - .start = 0x200, - .end = 0x2ff, - .flags = IORESOURCE_MEM, - }, { .start = IRQ_TC6393_MMC, .end = IRQ_TC6393_MMC, @@ -346,6 +337,50 @@ int tc6393xb_lcd_mode(struct platform_device *fb, } EXPORT_SYMBOL(tc6393xb_lcd_mode); +static int tc6393xb_mmc_enable(struct platform_device *mmc) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_enable(tc6393xb->scr + 0x200, 0, + tc6393xb_mmc_resources[0].start & 0xfffe); + + return 0; +} + +static int tc6393xb_mmc_resume(struct platform_device *mmc) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_resume(tc6393xb->scr + 0x200, 0, + tc6393xb_mmc_resources[0].start & 0xfffe); + + return 0; +} + +static void tc6393xb_mmc_pwr(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_pwr(tc6393xb->scr + 0x200, 0, state); +} + +static void tc6393xb_mmc_clk_div(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_clk_div(tc6393xb->scr + 0x200, 0, state); +} + +static struct tmio_mmc_data tc6393xb_mmc_data = { + .hclk = 24000000, + .set_pwr = tc6393xb_mmc_pwr, + .set_clk_div = tc6393xb_mmc_clk_div, +}; + static struct mfd_cell __devinitdata tc6393xb_cells[] = { [TC6393XB_CELL_NAND] = { .name = "tmio-nand", @@ -355,6 +390,8 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = { }, [TC6393XB_CELL_MMC] = { .name = "tmio-mmc", + .enable = tc6393xb_mmc_enable, + .resume = tc6393xb_mmc_resume, .driver_data = &tc6393xb_mmc_data, .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), .resources = tc6393xb_mmc_resources, @@ -836,3 +873,4 @@ MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer"); MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller"); MODULE_ALIAS("platform:tc6393xb"); + diff --git a/drivers/mfd/tmio_core.c b/drivers/mfd/tmio_core.c new file mode 100644 index 00000000000..eddc19ae464 --- /dev/null +++ b/drivers/mfd/tmio_core.c @@ -0,0 +1,52 @@ +/* + * Copyright(c) 2009 Ian Molton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base) +{ + /* Enable the MMC/SD Control registers */ + sd_config_write16(cnf, shift, CNF_CMD, SDCREN); + sd_config_write32(cnf, shift, CNF_CTL_BASE, base & 0xfffe); + + /* Disable SD power during suspend */ + sd_config_write8(cnf, shift, CNF_PWR_CTL_3, 0x01); + + /* The below is required but why? FIXME */ + sd_config_write8(cnf, shift, CNF_STOP_CLK_CTL, 0x1f); + + /* Power down SD bus */ + sd_config_write8(cnf, shift, CNF_PWR_CTL_2, 0x00); + + return 0; +} +EXPORT_SYMBOL(tmio_core_mmc_enable); + +int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base) +{ + + /* Enable the MMC/SD Control registers */ + sd_config_write16(cnf, shift, CNF_CMD, SDCREN); + sd_config_write32(cnf, shift, CNF_CTL_BASE, base & 0xfffe); + + return 0; +} +EXPORT_SYMBOL(tmio_core_mmc_resume); + +void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state) +{ + sd_config_write8(cnf, shift, CNF_PWR_CTL_2, state ? 0x02 : 0x00); +} +EXPORT_SYMBOL(tmio_core_mmc_pwr); + +void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state) +{ + sd_config_write8(cnf, shift, CNF_SD_CLK_MODE, state ? 1 : 0); +} +EXPORT_SYMBOL(tmio_core_mmc_clk_div); + diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 7cccc852374..e22c3fa3516 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -46,7 +46,9 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) clk |= 0x100; } - sd_config_write8(host, CNF_SD_CLK_MODE, clk >> 22); + if (host->set_clk_div) + host->set_clk_div(host->pdev, (clk>>22) & 1); + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff); } @@ -427,12 +429,13 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) /* Power sequence - OFF -> ON -> UP */ switch (ios->power_mode) { case MMC_POWER_OFF: /* power down SD bus */ - sd_config_write8(host, CNF_PWR_CTL_2, 0x00); + if (host->set_pwr) + host->set_pwr(host->pdev, 0); tmio_mmc_clk_stop(host); break; case MMC_POWER_ON: /* power up SD bus */ - - sd_config_write8(host, CNF_PWR_CTL_2, 0x02); + if (host->set_pwr) + host->set_pwr(host->pdev, 1); break; case MMC_POWER_UP: /* start bus clock */ tmio_mmc_clk_start(host); @@ -485,21 +488,15 @@ static int tmio_mmc_resume(struct platform_device *dev) { struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; struct mmc_host *mmc = platform_get_drvdata(dev); - struct tmio_mmc_host *host = mmc_priv(mmc); int ret = 0; /* Tell the MFD core we are ready to be enabled */ - if (cell->enable) { - ret = cell->enable(dev); + if (cell->resume) { + ret = cell->resume(dev); if (ret) goto out; } - /* Enable the MMC/SD Control registers */ - sd_config_write16(host, CNF_CMD, SDCREN); - sd_config_write32(host, CNF_CTL_BASE, - (dev->resource[0].start >> host->bus_shift) & 0xfffe); - mmc_resume_host(mmc); out: @@ -514,17 +511,16 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) { struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; struct tmio_mmc_data *pdata; - struct resource *res_ctl, *res_cnf; + struct resource *res_ctl; struct tmio_mmc_host *host; struct mmc_host *mmc; int ret = -EINVAL; - if (dev->num_resources != 3) + if (dev->num_resources != 2) goto out; res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0); - res_cnf = platform_get_resource(dev, IORESOURCE_MEM, 1); - if (!res_ctl || !res_cnf) + if (!res_ctl) goto out; pdata = cell->driver_data; @@ -539,8 +535,12 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) host = mmc_priv(mmc); host->mmc = mmc; + host->pdev = dev; platform_set_drvdata(dev, mmc); + host->set_pwr = pdata->set_pwr; + host->set_clk_div = pdata->set_clk_div; + /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ host->bus_shift = resource_size(res_ctl) >> 10; @@ -548,10 +548,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) if (!host->ctl) goto host_free; - host->cnf = ioremap(res_cnf->start, resource_size(res_cnf)); - if (!host->cnf) - goto unmap_ctl; - mmc->ops = &tmio_mmc_ops; mmc->caps = MMC_CAP_4_BIT_DATA; mmc->f_max = pdata->hclk; @@ -562,23 +558,9 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) if (cell->enable) { ret = cell->enable(dev); if (ret) - goto unmap_cnf; + goto unmap_ctl; } - /* Enable the MMC/SD Control registers */ - sd_config_write16(host, CNF_CMD, SDCREN); - sd_config_write32(host, CNF_CTL_BASE, - (dev->resource[0].start >> host->bus_shift) & 0xfffe); - - /* Disable SD power during suspend */ - sd_config_write8(host, CNF_PWR_CTL_3, 0x01); - - /* The below is required but why? FIXME */ - sd_config_write8(host, CNF_STOP_CLK_CTL, 0x1f); - - /* Power down SD bus*/ - sd_config_write8(host, CNF_PWR_CTL_2, 0x00); - tmio_mmc_clk_stop(host); reset(host); @@ -586,14 +568,14 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) if (ret >= 0) host->irq = ret; else - goto unmap_cnf; + goto unmap_ctl; disable_mmc_irqs(host, TMIO_MASK_ALL); ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host); if (ret) - goto unmap_cnf; + goto unmap_ctl; mmc_add_host(mmc); @@ -605,8 +587,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) return 0; -unmap_cnf: - iounmap(host->cnf); unmap_ctl: iounmap(host->ctl); host_free: @@ -626,7 +606,6 @@ static int __devexit tmio_mmc_remove(struct platform_device *dev) mmc_remove_host(mmc); free_irq(host->irq, host); iounmap(host->ctl); - iounmap(host->cnf); mmc_free_host(mmc); } diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 9fa99859497..692dc23363b 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -11,26 +11,6 @@ #include -#define CNF_CMD 0x04 -#define CNF_CTL_BASE 0x10 -#define CNF_INT_PIN 0x3d -#define CNF_STOP_CLK_CTL 0x40 -#define CNF_GCLK_CTL 0x41 -#define CNF_SD_CLK_MODE 0x42 -#define CNF_PIN_STATUS 0x44 -#define CNF_PWR_CTL_1 0x48 -#define CNF_PWR_CTL_2 0x49 -#define CNF_PWR_CTL_3 0x4a -#define CNF_CARD_DETECT_MODE 0x4c -#define CNF_SD_SLOT 0x50 -#define CNF_EXT_GCLK_CTL_1 0xf0 -#define CNF_EXT_GCLK_CTL_2 0xf1 -#define CNF_EXT_GCLK_CTL_3 0xf9 -#define CNF_SD_LED_EN_1 0xfa -#define CNF_SD_LED_EN_2 0xfe - -#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/ - #define CTL_SD_CMD 0x00 #define CTL_ARG_REG 0x04 #define CTL_STOP_INTERNAL_ACTION 0x08 @@ -110,7 +90,6 @@ struct tmio_mmc_host { - void __iomem *cnf; void __iomem *ctl; unsigned long bus_shift; struct mmc_command *cmd; @@ -119,10 +98,16 @@ struct tmio_mmc_host { struct mmc_host *mmc; int irq; + /* Callbacks for clock / power control */ + void (*set_pwr)(struct platform_device *host, int state); + void (*set_clk_div)(struct platform_device *host, int state); + /* pio related stuff */ struct scatterlist *sg_ptr; unsigned int sg_len; unsigned int sg_off; + + struct platform_device *pdev; }; #include @@ -163,25 +148,6 @@ static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); } -static inline void sd_config_write8(struct tmio_mmc_host *host, int addr, - u8 val) -{ - writeb(val, host->cnf + (addr << host->bus_shift)); -} - -static inline void sd_config_write16(struct tmio_mmc_host *host, int addr, - u16 val) -{ - writew(val, host->cnf + (addr << host->bus_shift)); -} - -static inline void sd_config_write32(struct tmio_mmc_host *host, int addr, - u32 val) -{ - writew(val, host->cnf + (addr << host->bus_shift)); - writew(val >> 16, host->cnf + ((addr + 2) << host->bus_shift)); -} - #include #include diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index 6b9c5d06690..9cb1834deff 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h @@ -2,6 +2,8 @@ #define MFD_TMIO_H #include +#include +#include #define tmio_ioread8(addr) readb(addr) #define tmio_ioread16(addr) readw(addr) @@ -18,11 +20,48 @@ writew((val) >> 16, (addr) + 2); \ } while (0) +#define CNF_CMD 0x04 +#define CNF_CTL_BASE 0x10 +#define CNF_INT_PIN 0x3d +#define CNF_STOP_CLK_CTL 0x40 +#define CNF_GCLK_CTL 0x41 +#define CNF_SD_CLK_MODE 0x42 +#define CNF_PIN_STATUS 0x44 +#define CNF_PWR_CTL_1 0x48 +#define CNF_PWR_CTL_2 0x49 +#define CNF_PWR_CTL_3 0x4a +#define CNF_CARD_DETECT_MODE 0x4c +#define CNF_SD_SLOT 0x50 +#define CNF_EXT_GCLK_CTL_1 0xf0 +#define CNF_EXT_GCLK_CTL_2 0xf1 +#define CNF_EXT_GCLK_CTL_3 0xf9 +#define CNF_SD_LED_EN_1 0xfa +#define CNF_SD_LED_EN_2 0xfe + +#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/ + +#define sd_config_write8(base, shift, reg, val) \ + tmio_iowrite8((val), (base) + ((reg) << (shift))) +#define sd_config_write16(base, shift, reg, val) \ + tmio_iowrite16((val), (base) + ((reg) << (shift))) +#define sd_config_write32(base, shift, reg, val) \ + do { \ + tmio_iowrite16((val), (base) + ((reg) << (shift))); \ + tmio_iowrite16((val) >> 16, (base) + ((reg + 2) << (shift))); \ + } while (0) + +int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base); +int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base); +void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state); +void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state); + /* * data for the MMC controller */ struct tmio_mmc_data { const unsigned int hclk; + void (*set_pwr)(struct platform_device *host, int state); + void (*set_clk_div)(struct platform_device *host, int state); }; /* -- cgit v1.2.3-70-g09d2 From 8e6ba2dfa2d6c4691a83a63e211990a8bd7b788b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 7 Jan 2010 16:16:14 +0000 Subject: mfd: WM835x GPIO direction register is not locked No need to set the security key when writing to it. Signed-off-by: Mark Brown Cc: stable@kernel.org Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8350-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 8485a701806..9a970bd6877 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -134,8 +134,7 @@ static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg) wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY) return 0; - if ((reg == WM8350_GPIO_CONFIGURATION_I_O) || - (reg >= WM8350_GPIO_FUNCTION_SELECT_1 && + if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 && reg <= WM8350_GPIO_FUNCTION_SELECT_4) || (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) -- cgit v1.2.3-70-g09d2 From 1e02b2c32484bfe0c5564d9be060b7d9821307b9 Mon Sep 17 00:00:00 2001 From: Alberto Panizzo Date: Mon, 14 Dec 2009 18:18:05 +0100 Subject: mfd: Unlock mc13783 before subsystems initialisation, at probe time. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this, mc13783 subsystems drivers can configure the mc13783 chip reading and writing registers. Signed-off-by: Alberto Panizzo Acked-by: Uwe Kleine-König Signed-off-by: Samuel Ortiz --- drivers/mfd/mc13783-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c index a1ade2324ea..735c8a4d164 100644 --- a/drivers/mfd/mc13783-core.c +++ b/drivers/mfd/mc13783-core.c @@ -619,6 +619,8 @@ err_revision: } /* This should go away (END) */ + mc13783_unlock(mc13783); + if (pdata->flags & MC13783_USE_ADC) mc13783_add_subdevice(mc13783, "mc13783-adc"); @@ -641,8 +643,6 @@ err_revision: if (pdata->flags & MC13783_USE_TOUCHSCREEN) mc13783_add_subdevice(mc13783, "mc13783-ts"); - mc13783_unlock(mc13783); - return 0; } -- cgit v1.2.3-70-g09d2 From ebddd63b74dcf1cb676d14328d5852f1fee19a8a Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 18 Jan 2010 16:43:44 +0200 Subject: UBI: fix memory leak in update path When truncating an UBI volume, UBI should allocates a PEB-sized buffer but does not release it, which leads to memory leaks. This patch fixes the issue. Reported-by: Marek Skuczynski Signed-off-by: Artem Bityutskiy Tested-by: Marek Skuczynski Cc: stable@kernel.org --- drivers/mtd/ubi/upd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index c1d7b880c79..425bf5a3edd 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -155,6 +155,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, if (err) return err; vol->updating = 0; + return 0; } vol->upd_buf = vmalloc(ubi->leb_size); -- cgit v1.2.3-70-g09d2 From 1152dcc28c66a74b5b3f1a3ede0aa6729bfd48e4 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 15 Jan 2010 13:42:58 -0800 Subject: iwlwifi: Fix throughput stall issue in HT mode for 5000 Similar to 6000 and 1000 series, RTS/CTS is the recommended protection mechanism for 5000 series in HT mode based on the HW design. Using RTS/CTS will better protect the inner exchange from interference, especially in highly-congested environment, it also prevent uCode encounter TX FIFO underrun and other HT mode related performance issues. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre CC: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 33a5866538e..de45f308b74 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1598,6 +1598,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .use_bsm = false, .ht_greenfield_support = true, .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; @@ -1622,6 +1623,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .use_bsm = false, .ht_greenfield_support = true, .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, }; @@ -1667,6 +1669,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .use_bsm = false, .ht_greenfield_support = true, .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; @@ -1691,6 +1694,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .use_bsm = false, .ht_greenfield_support = true, .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; @@ -1715,6 +1719,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .use_bsm = false, .ht_greenfield_support = true, .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; -- cgit v1.2.3-70-g09d2 From bb5d2db5709e469f4a8c01eaaee9a275ed9772aa Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 15 Jan 2010 13:42:59 -0800 Subject: iwlwifi: add license to tracing files Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-devtrace.c | 26 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-devtrace.h | 26 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index e7d88d1da15..83cc4e500a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c @@ -1,3 +1,29 @@ +/****************************************************************************** + * + * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + #include /* sparse doesn't like tracepoint macros */ diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 21361968ab7..d9c7363b1bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -1,3 +1,29 @@ +/****************************************************************************** + * + * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + #if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ) #define __IWLWIFI_DEVICE_TRACE -- cgit v1.2.3-70-g09d2 From f5300e04df78feae8107c1846dd3a9e27c071b2f Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 18 Jan 2010 00:07:38 +0100 Subject: p54pci: rx frame length check A long time ago, a user reported several crashes due to data corruptions which are likely the result of a not-100%-supported, or faulty? PCI bridge. ( http://patchwork.kernel.org/patch/53004/ ) This patch fixes entry #1. "1. p54p_check_rx_ring - skb_over_panic: Under a ping flood or just left running for a bit would panic with a skb_over_panic." As described in the mail: The invalid frame length causes skb_put to bailout and trigger a crash. Note: Simply dropping the frame is problematic, because if its content contains a tx feedback we would lose some portion of the device memory space.... And the driver/mac80211 should handle all other invalid data. Reported-by: Quintin Pitts Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index a15962a19b2..a72f7c2577d 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -197,6 +197,14 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index, i %= ring_limit; continue; } + + if (unlikely(len > priv->common.rx_mtu)) { + if (net_ratelimit()) + dev_err(&priv->pdev->dev, "rx'd frame size " + "exceeds length threshold.\n"); + + len = priv->common.rx_mtu; + } skb_put(skb, len); if (p54_rx(dev, skb)) { -- cgit v1.2.3-70-g09d2 From ad580db50ee8dccd069ffcd76d6f70fa6d4a62a8 Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Mon, 18 Jan 2010 01:24:11 +0000 Subject: zd1211rw: adding 0409:0248 to supported device list Yasuhiro ABE reported success in sourceforge zd1211-dev list. The device is a NEC Aterm WL54GU usb wireless stick. The brand and retail product name NEC, Aterm PA-WL54GU The USB ID's (duh) ID 0409:0248 The chip ID string zd1211rw 1-1:1.0: zd1211b chip 0409:0248 v4810 high 00-1b-8b AL2230S_RF pa0 g--N- The FCC ID unknown Signed-off-by: Hin-Tak Leung Signed-off-by: Yasuhiro ABE Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index ac19ecd19cf..72d3e437e19 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -62,6 +62,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x0409, 0x0248), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, -- cgit v1.2.3-70-g09d2 From 3c9d8eccd8687f0e770e4d89fd0d73d4f81a985a Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Thu, 14 Jan 2010 20:58:05 +0000 Subject: [WATCHDOG] iTCO_wdt: Add Intel Cougar Point and PCH DeviceIDs This patch adds the Intel Cougar Point and PCH DeviceIDs for iTCO Watchdog. Signed-off-by: Seth Heasley Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index c8a3bec2683..4bdb7f1a907 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -29,8 +29,9 @@ * document number 313056-003, 313057-017: 82801H (ICH8) * document number 316972-004, 316973-012: 82801I (ICH9) * document number 319973-002, 319974-002: 82801J (ICH10) - * document number 322169-001, 322170-001: 5 Series, 3400 Series (PCH) + * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) * document number 320066-003, 320257-008: EP80597 (IICH) + * document number TBD : Cougar Point (CPT) */ /* @@ -100,8 +101,22 @@ enum iTCO_chipsets { TCO_ICH10DO, /* ICH10DO */ TCO_PCH, /* PCH Desktop Full Featured */ TCO_PCHM, /* PCH Mobile Full Featured */ + TCO_P55, /* P55 */ + TCO_PM55, /* PM55 */ + TCO_H55, /* H55 */ + TCO_QM57, /* QM57 */ + TCO_H57, /* H57 */ + TCO_HM55, /* HM55 */ + TCO_Q57, /* Q57 */ + TCO_HM57, /* HM57 */ TCO_PCHMSFF, /* PCH Mobile SFF Full Featured */ + TCO_QS57, /* QS57 */ + TCO_3400, /* 3400 */ + TCO_3420, /* 3420 */ + TCO_3450, /* 3450 */ TCO_EP80579, /* EP80579 */ + TCO_CPTD, /* CPT Desktop */ + TCO_CPTM, /* CPT Mobile */ }; static struct { @@ -144,8 +159,22 @@ static struct { {"ICH10DO", 2}, {"PCH Desktop Full Featured", 2}, {"PCH Mobile Full Featured", 2}, + {"P55", 2}, + {"PM55", 2}, + {"H55", 2}, + {"QM57", 2}, + {"H57", 2}, + {"HM55", 2}, + {"Q57", 2}, + {"HM57", 2}, {"PCH Mobile SFF Full Featured", 2}, + {"QS57", 2}, + {"3400", 2}, + {"3420", 2}, + {"3450", 2}, {"EP80579", 2}, + {"CPT Desktop", 2}, + {"CPT Mobile", 2}, {NULL, 0} }; @@ -216,8 +245,22 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x3a14, TCO_ICH10DO)}, { ITCO_PCI_DEVICE(0x3b00, TCO_PCH)}, { ITCO_PCI_DEVICE(0x3b01, TCO_PCHM)}, + { ITCO_PCI_DEVICE(0x3b02, TCO_P55)}, + { ITCO_PCI_DEVICE(0x3b03, TCO_PM55)}, + { ITCO_PCI_DEVICE(0x3b06, TCO_H55)}, + { ITCO_PCI_DEVICE(0x3b07, TCO_QM57)}, + { ITCO_PCI_DEVICE(0x3b08, TCO_H57)}, + { ITCO_PCI_DEVICE(0x3b09, TCO_HM55)}, + { ITCO_PCI_DEVICE(0x3b0a, TCO_Q57)}, + { ITCO_PCI_DEVICE(0x3b0b, TCO_HM57)}, { ITCO_PCI_DEVICE(0x3b0d, TCO_PCHMSFF)}, + { ITCO_PCI_DEVICE(0x3b0f, TCO_QS57)}, + { ITCO_PCI_DEVICE(0x3b12, TCO_3400)}, + { ITCO_PCI_DEVICE(0x3b14, TCO_3420)}, + { ITCO_PCI_DEVICE(0x3b16, TCO_3450)}, { ITCO_PCI_DEVICE(0x5031, TCO_EP80579)}, + { ITCO_PCI_DEVICE(0x1c42, TCO_CPTD)}, + { ITCO_PCI_DEVICE(0x1c43, TCO_CPTM)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); -- cgit v1.2.3-70-g09d2 From 4f9c85a1b03bfa5c0a0d8488a3a7766f3c9fb756 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 18 Jan 2010 05:37:16 +0000 Subject: phylib: Move workqueue initialization to a proper place commit 541cd3ee00a4fe975b22fac6a3bc846bacef37f7 ("phylib: Fix deadlock on resume") caused TI DaVinci EMAC ethernet driver to oops upon resume: PM: resume of devices complete after 237.098 msecs Restarting tasks ... done. kernel BUG at kernel/workqueue.c:354! Unable to handle kernel NULL pointer dereference at virtual address 00000000 [...] Backtrace: [] (__bug+0x0/0x2c) from [] (queue_delayed_work_on+0x74/0xf8) [] (queue_delayed_work_on+0x0/0xf8) from [] (queue_delayed_work+0x2c/0x30) The oops pops up because TI DaVinci EMAC driver detaches PHY on suspend and attaches it back on resume. Attaching makes phylib call phy_start_machine() that initializes a workqueue. On the other hand, PHY's resume routine will call phy_start_machine() again, and that will cause the oops since we just destroyed the already scheduled workqueue. This patch fixes the issue by moving workqueue initialization to phy_device_create(). p.s. We don't see this oops with ucc_geth and gianfar drivers because they perform a fine-grained suspend, i.e. they just stop the PHYs without detaching. Reported-by: Sekhar Nori Signed-off-by: Anton Vorontsov Tested-by: Sekhar Nori Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 4 +--- drivers/net/phy/phy_device.c | 1 + include/linux/phy.h | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index b0e9f9c5172..0295097d6c4 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -410,7 +410,6 @@ EXPORT_SYMBOL(phy_start_aneg); static void phy_change(struct work_struct *work); -static void phy_state_machine(struct work_struct *work); /** * phy_start_machine - start PHY state machine tracking @@ -430,7 +429,6 @@ void phy_start_machine(struct phy_device *phydev, { phydev->adjust_state = handler; - INIT_DELAYED_WORK(&phydev->state_queue, phy_state_machine); schedule_delayed_work(&phydev->state_queue, HZ); } @@ -761,7 +759,7 @@ EXPORT_SYMBOL(phy_start); * phy_state_machine - Handle the state machine * @work: work_struct that describes the work to be done */ -static void phy_state_machine(struct work_struct *work) +void phy_state_machine(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); struct phy_device *phydev = diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8212b2b9342..adbc0fded13 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -177,6 +177,7 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) dev->state = PHY_DOWN; mutex_init(&dev->lock); + INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); return dev; } diff --git a/include/linux/phy.h b/include/linux/phy.h index 7968defd2fa..6a7eb402165 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -485,6 +485,7 @@ void phy_driver_unregister(struct phy_driver *drv); int phy_driver_register(struct phy_driver *new_driver); void phy_prepare_link(struct phy_device *phydev, void (*adjust_link)(struct net_device *)); +void phy_state_machine(struct work_struct *work); void phy_start_machine(struct phy_device *phydev, void (*handler)(struct net_device *)); void phy_stop_machine(struct phy_device *phydev); -- cgit v1.2.3-70-g09d2 From 34692421bc7d6145ef383b014860f4fde10b7505 Mon Sep 17 00:00:00 2001 From: Jiajun Wu Date: Mon, 18 Jan 2010 05:47:50 +0000 Subject: ucc_geth: Fix full TX queue processing commit 7583605b6d29f1f7f6fc505b883328089f3485ad ("ucc_geth: Fix empty TX queue processing") fixed empty TX queue mishandling, but didn't account another corner case: when TX queue becomes full. Without this patch the driver will stop transmiting when TX queue becomes full since 'bd == ugeth->txBd[txQ]' actually checks for two things: queue empty or full. Let's better check for NULL skb, which unambiguously signals an empty queue. Signed-off-by: Jiajun Wu Signed-off-by: Anton Vorontsov Cc: Stable [2.6.32] Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 96bdc0b4388..eb8fe7e16c6 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3279,13 +3279,12 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) /* Handle the transmitted buffer and release */ /* the BD to be used with the current frame */ - if (bd == ugeth->txBd[txQ]) /* queue empty? */ + skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]; + if (!skb) break; dev->stats.tx_packets++; - skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]; - if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN && skb_recycle_check(skb, ugeth->ug_info->uf_info.max_rx_buf_length + -- cgit v1.2.3-70-g09d2 From 357d46a17e54c9a87e0e6ef3930ff4ab2d232b81 Mon Sep 17 00:00:00 2001 From: Matthew Slattery Date: Mon, 18 Jan 2010 05:47:16 +0000 Subject: sfc: QT202x: Remove unreliable MMD check at initialisation Checking the PHY XS MMD here is unnecessary and can give false negatives. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/qt202x_phy.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c index ff8f0a417fa..e0d13a45101 100644 --- a/drivers/net/sfc/qt202x_phy.c +++ b/drivers/net/sfc/qt202x_phy.c @@ -318,12 +318,6 @@ static int qt202x_reset_phy(struct efx_nic *efx) /* Wait 250ms for the PHY to complete bootup */ msleep(250); - /* Check that all the MMDs we expect are present and responding. We - * expect faults on some if the link is down, but not on the PHY XS */ - rc = efx_mdio_check_mmds(efx, QT202X_REQUIRED_DEVS, MDIO_DEVS_PHYXS); - if (rc < 0) - goto fail; - falcon_board(efx)->type->init_phy(efx); return rc; -- cgit v1.2.3-70-g09d2 From 98f672ca9978c6e5997dbe905c91a73593148a7e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 18 Jan 2010 21:14:12 +0000 Subject: bfin_mac: use the newer CLKBUFOE bit name via asm/dpmc.h This driver tweaks VR_CTL, so pull in the header for the bit defines. Also switch to the new define name as the old one has gone away. Signed-off-by: Mike Frysinger Signed-off-by: David S. Miller --- drivers/net/bfin_mac.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 8ffea3990d0..0b23bc4f56c 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -386,8 +387,8 @@ static int mii_probe(struct net_device *dev) u32 sclk, mdc_div; /* Enable PHY output early */ - if (!(bfin_read_VR_CTL() & PHYCLKOE)) - bfin_write_VR_CTL(bfin_read_VR_CTL() | PHYCLKOE); + if (!(bfin_read_VR_CTL() & CLKBUFOE)) + bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE); sclk = get_sclk(); mdc_div = ((sclk / MDC_CLK) / 2) - 1; -- cgit v1.2.3-70-g09d2 From 2d146eb172d5f754e3973a3f761f7619ebb12df9 Mon Sep 17 00:00:00 2001 From: Ram Vepa Date: Tue, 19 Jan 2010 12:36:20 -0800 Subject: S2io: two branches the same in wait_for_cmd_complete() Fix check to verify if a register bit is set. We have not hit this bug because wait_for_cmd_complete() is always called with S2IO_BIT_RESET. Reported by Roel Kluin . Signed-off-by: Ram Vepa Signed-off-by: David S. Miller --- drivers/net/s2io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index cc4218667cb..3c4836d0898 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -3421,7 +3421,7 @@ static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit, break; } } else { - if (!(val64 & busy_bit)) { + if (val64 & busy_bit) { ret = SUCCESS; break; } -- cgit v1.2.3-70-g09d2 From e605d554ec17be55741b066387ae9f341777f52c Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 7 Jan 2010 03:35:49 +0100 Subject: [WATCHDOG] ixp2000: Fix build failure caused by missing include This patch fixes a build failure[1] caused by the missing include of timer.h and thus fixes the build failure. Notably the build failure existed since October 2009! [2] References: [1] http://kisskb.ellerman.id.au/kisskb/buildresult/1983339/ [2] http://kisskb.ellerman.id.au/kisskb/buildresult/1351737/ Signed-off-by: Peter Huewe Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/ixp2000_wdt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c index 4f4b35a20d8..3c79dc58795 100644 --- a/drivers/watchdog/ixp2000_wdt.c +++ b/drivers/watchdog/ixp2000_wdt.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3-70-g09d2 From 2205cbe8ecaf5f3ab911cef839c94d05ea5b0c76 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Tue, 19 Jan 2010 16:55:41 -0700 Subject: ACPI: processor: restrict early _PDC to opt-in platforms Commit 78f1699 (ACPI: processor: call _PDC early) blindly walks the namespace and calls _PDC on every processor object it finds. This change may cause issues on platforms that declare dummy values for SSDTs on non-present processors (disabled in MADT). When we call _PDC and dynamically attempt to execute the AML Load() op on these dummy SSDTs, there's no telling what might happen. Rather than finding every platform that has bogus SSDTs, restrict early _PDC calls to platforms that are known to need early evaluation of _PDC. This is a minimal, temporary fix (given the context of the current release cycle). A real solution of checking the MADT for non-present processors will be written for the next merge window. References: http://bugzilla.kernel.org/show_bug.cgi?id=14710 http://bugzilla.kernel.org/show_bug.cgi?id=14954 Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 30e4dc0cdf3..f3364371207 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -144,6 +144,29 @@ void acpi_processor_set_pdc(acpi_handle handle) } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); +static int early_pdc_optin; +static int set_early_pdc_optin(const struct dmi_system_id *id) +{ + early_pdc_optin = 1; + return 0; +} + +static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = { + { + set_early_pdc_optin, "HP Envy", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL}, + { + set_early_pdc_optin, "HP Pavilion dv6", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL}, + { + set_early_pdc_optin, "HP Pavilion dv7", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL}, + {}, +}; + static acpi_status early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) { @@ -159,6 +182,13 @@ void acpi_early_processor_set_pdc(void) */ dmi_check_system(processor_idle_dmi_table); + /* + * Allow systems to opt-in to early _PDC evaluation. + */ + dmi_check_system(early_pdc_optin_table); + if (!early_pdc_optin) + return; + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, early_init_pdc, NULL, NULL, NULL); -- cgit v1.2.3-70-g09d2 From 7f07a605a3929d2d94dcbad8ccb7d280958d21f9 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Tue, 12 Jan 2010 23:37:07 +1100 Subject: ACPI: power_meter: remove double kfree() resource->domain_devices can be double kfree()'d in a couple of places. Fix this by setting num_domain_devices = 0 after the kfree(). Coverity CID: 13356, 13355, 13354 Signed-off-by: Darren Jenkins Acked-by: Darrick J. Wong Signed-off-by: Len Brown --- drivers/acpi/power_meter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index ca75c36f754..dc4ffadf812 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c @@ -534,6 +534,7 @@ static void remove_domain_devices(struct acpi_power_meter_resource *resource) kfree(resource->domain_devices); kobject_put(resource->holders_dir); + resource->num_domain_devices = 0; } static int read_domain_devices(struct acpi_power_meter_resource *resource) @@ -740,7 +741,6 @@ skip_unsafe_cap: return res; error: - remove_domain_devices(resource); remove_attrs(resource); return res; } -- cgit v1.2.3-70-g09d2 From 5d76b6f6c17572e662f5c99c2023adae92100855 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 19 Jan 2010 22:41:14 -0500 Subject: ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C Linux has always ignored ACPI BIOS C2 with exit latency > 100 usec, and the ACPI spec is clear that is correct FADT-supplied C2. However, the ACPI spec explicitly states that _CST-supplied C-states have no latency limits. So move the 100usec C2 test out of the code shared by FADT and _CST code-paths, and into the FADT-specific path. This bug has not been visible until Nehalem, which advertises a CPU-C2 worst case exit latency on servers of 205usec. That (incorrect) figure is being used by BIOS writers on mobile Nehalem systems for the AC configuration. Thus, Linux ignores C2 leaving just C1, which is saves less power, and also impacts performance by preventing the use of turbo mode. http://bugzilla.kernel.org/show_bug.cgi?id=15064 Tested-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d1676b1754d..8f6da9acc8e 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -305,6 +305,17 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; + /* + * FADT specified C2 latency must be less than or equal to + * 100 microseconds. + */ + if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency)); + /* invalidate C2 */ + pr->power.states[ACPI_STATE_C2].address = 0; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "lvl2[0x%08x] lvl3[0x%08x]\n", pr->power.states[ACPI_STATE_C2].address, @@ -500,16 +511,6 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) if (!cx->address) return; - /* - * C2 latency must be less than or equal to 100 - * microseconds. - */ - else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "latency too large [%d]\n", cx->latency)); - return; - } - /* * Otherwise we've met all of our C2 requirements. * Normalize the C2 latency to expidite policy -- cgit v1.2.3-70-g09d2 From a6d72c189f6c4292ba1a323e8af24083790529f8 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 19 Jan 2010 23:10:04 -0500 Subject: ACPI: allow C3 > 1000usec Do for C3 what the previous patch did for C2. The C2 patch was in response to a highly visible and multiply reported C-state/turbo failure, while this change has no bug report in-hand. This will enable C3 in Linux on systems where BIOS overstates C3 latency in _CST. It will also enable future systems which may actually have C3 > 1000usec. Linux has always ignored ACPI BIOS C3 with exit latency > 1000 usec, and the ACPI spec is clear that is correct FADT-supplied C3. However, the ACPI spec explicitly states that _CST-supplied C-states have no latency limits. So move the 1000usec C3 test out of the code shared by FADT and _CST code-paths, and into the FADT-specific path. Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 8f6da9acc8e..2c543b42eb1 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -316,6 +316,17 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) pr->power.states[ACPI_STATE_C2].address = 0; } + /* + * FADT supplied C3 latency must be less than or equal to + * 1000 microseconds. + */ + if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency)); + /* invalidate C3 */ + pr->power.states[ACPI_STATE_C3].address = 0; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "lvl2[0x%08x] lvl3[0x%08x]\n", pr->power.states[ACPI_STATE_C2].address, @@ -532,16 +543,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, if (!cx->address) return; - /* - * C3 latency must be less than or equal to 1000 - * microseconds. - */ - else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "latency too large [%d]\n", cx->latency)); - return; - } - /* * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) * DMA transfers are used by any ISA device to avoid livelock. -- cgit v1.2.3-70-g09d2 From d22edd293ff3f1e2d252f164fe2cf744620cb660 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 19 Jan 2010 23:29:09 -0500 Subject: ACPI: delete acpi_processor_power_verify_c2() no functional change -- cleanup only. acpi_processor_power_verify_c2() was nearly empty due to a previous patch, so expand its remains into its one caller and delete it. Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2c543b42eb1..7c0441f63b3 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -516,23 +516,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) return status; } -static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) -{ - - if (!cx->address) - return; - - /* - * Otherwise we've met all of our C2 requirements. - * Normalize the C2 latency to expidite policy - */ - cx->valid = 1; - - cx->latency_ticks = cx->latency; - - return; -} - static void acpi_processor_power_verify_c3(struct acpi_processor *pr, struct acpi_processor_cx *cx) { @@ -631,7 +614,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) break; case ACPI_STATE_C2: - acpi_processor_power_verify_c2(cx); + if (!cx->address) + break; + cx->valid = 1; + cx->latency_ticks = cx->latency; /* Normalize latency */ break; case ACPI_STATE_C3: -- cgit v1.2.3-70-g09d2 From 534ead709235b967b659947c55d9130873a432c4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 14 Jan 2010 16:18:09 +0900 Subject: libata: retry FS IOs even if it has failed with AC_ERR_INVALID libata currently doesn't retry if a command fails with AC_ERR_INVALID assuming that retrying won't get it any further even if retried. However, a failure may be classified as invalid through hardware glitch (incorrect reading of the error register or firmware bug) and there isn't whole lot to gain by not retrying as actually invalid commands will be failed immediately. Also, commands serving FS IOs are extremely unlikely to be invalid. Retry FS IOs even if it's marked invalid. Transient and incorrect invalid failure was seen while debugging firmware related issue on Samsung n130 on bko#14314. http://bugzilla.kernel.org/show_bug.cgi?id=14314 Signed-off-by: Tejun Heo Reported-by: Johannes Stezenbach Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 0ea97c942ce..9f6cfac0f2c 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2028,8 +2028,9 @@ static void ata_eh_link_autopsy(struct ata_link *link) qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); /* determine whether the command is worth retrying */ - if (!(qc->err_mask & AC_ERR_INVALID) && - ((qc->flags & ATA_QCFLAG_IO) || qc->err_mask != AC_ERR_DEV)) + if (qc->flags & ATA_QCFLAG_IO || + (!(qc->err_mask & AC_ERR_INVALID) && + qc->err_mask != AC_ERR_DEV)) qc->flags |= ATA_QCFLAG_RETRY; /* accumulate error info */ -- cgit v1.2.3-70-g09d2 From f3d1ccc14f37a07614c67a270f05a8d94ec3667c Mon Sep 17 00:00:00 2001 From: Andrew Randrianasulu Date: Wed, 20 Jan 2010 11:36:30 -0500 Subject: drm/radeon/kms/r200: fix bug in CS parser The checks for CUBE and 3D textures were inverted. fixes fdo bug 24159 agd5f: added comments for clarity. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r200.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c index 20942127c46..ff1e0cd608b 100644 --- a/drivers/gpu/drm/radeon/r200.c +++ b/drivers/gpu/drm/radeon/r200.c @@ -371,13 +371,16 @@ int r200_packet0_check(struct radeon_cs_parser *p, case 5: case 6: case 7: + /* 1D/2D */ track->textures[i].tex_coord_type = 0; break; case 1: - track->textures[i].tex_coord_type = 1; + /* CUBE */ + track->textures[i].tex_coord_type = 2; break; case 2: - track->textures[i].tex_coord_type = 2; + /* 3D */ + track->textures[i].tex_coord_type = 1; break; } break; -- cgit v1.2.3-70-g09d2 From 828153e29206196552c2cc34461ad7e5b93e3f22 Mon Sep 17 00:00:00 2001 From: Andrew Randrianasulu Date: Wed, 20 Jan 2010 11:56:07 -0500 Subject: drm/radeon/kms/r200: fix bug in CS parser Add missing vertex shader regs for r200. fixed fdo bug 26061 agd5f: use official reg names Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/reg_srcs/r200 | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/reg_srcs/r200 b/drivers/gpu/drm/radeon/reg_srcs/r200 index 6021c8849a1..c29ac434ac9 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r200 +++ b/drivers/gpu/drm/radeon/reg_srcs/r200 @@ -91,6 +91,8 @@ r200 0x3294 0x22b8 SE_TCL_TEX_CYL_WRAP_CTL 0x22c0 SE_TCL_UCP_VERT_BLEND_CNTL 0x22c4 SE_TCL_POINT_SPRITE_CNTL +0x22d0 SE_PVS_CNTL +0x22d4 SE_PVS_CONST_CNTL 0x2648 RE_POINTSIZE 0x26c0 RE_TOP_LEFT 0x26c4 RE_MISC -- cgit v1.2.3-70-g09d2 From cf57fc7aa2ac61d02a29550b99db6a01ccd7917c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 18 Jan 2010 20:20:07 -0500 Subject: drm/radeon/kms/r100: fix bug in CS parser The first dword of PACKET3_3D_DRAW_IMMD maps to SE_VTX_FMT so the vertex size is part of the draw packet. This patch fixes a possible case where you have a command buffer that does not contain SE_VTX_FMT register write, but does contain PACKET3_3D_DRAW_IMMD. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 62b27bede65..11c9a3fe681 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1504,6 +1504,7 @@ static int r100_packet3_check(struct radeon_cs_parser *p, DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); return -EINVAL; } + track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 0)); track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); track->immd_dwords = pkt->count - 1; r = r100_cs_track_check(p->rdev, track); -- cgit v1.2.3-70-g09d2 From 07bec2df01cde5590a1700b992d12de3f46b12bc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 13 Jan 2010 19:09:12 -0500 Subject: drm/radeon/kms: fix hardcoded mmio size in register functions newer asics have large mmio apertures Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ab37dd0f2e7..c23278240a4 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -847,7 +847,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev, static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) { - if (reg < 0x10000) + if (reg < rdev->rmmio_size) return readl(((void __iomem *)rdev->rmmio) + reg); else { writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); @@ -857,7 +857,7 @@ static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) { - if (reg < 0x10000) + if (reg < rdev->rmmio_size) writel(v, ((void __iomem *)rdev->rmmio) + reg); else { writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); -- cgit v1.2.3-70-g09d2 From 9f53e7931610cbd1715fd2d2c0f9a853e17f02d8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 19 Jan 2010 12:38:48 -0500 Subject: drm/radeon/kms/atom: fix some parser bugs - add support for inline src params - fix shift_left/shift_right and shl/shr ops shift_* ops use inline src params, shl/r use full params - fix mask op (uses inline params) Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atom.c | 90 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 388140a7e65..9a3378184e1 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -385,6 +385,32 @@ static uint32_t atom_get_src(atom_exec_context *ctx, uint8_t attr, int *ptr) return atom_get_src_int(ctx, attr, ptr, NULL, 1); } +static uint32_t atom_get_src_direct(atom_exec_context *ctx, uint8_t align, int *ptr) +{ + uint32_t val = 0xCDCDCDCD; + + switch (align) { + case ATOM_SRC_DWORD: + val = U32(*ptr); + (*ptr) += 4; + break; + case ATOM_SRC_WORD0: + case ATOM_SRC_WORD8: + case ATOM_SRC_WORD16: + val = U16(*ptr); + (*ptr) += 2; + break; + case ATOM_SRC_BYTE0: + case ATOM_SRC_BYTE8: + case ATOM_SRC_BYTE16: + case ATOM_SRC_BYTE24: + val = U8(*ptr); + (*ptr)++; + break; + } + return val; +} + static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr, int *ptr, uint32_t *saved, int print) { @@ -677,9 +703,9 @@ static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg) SDEBUG(" dst: "); dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); SDEBUG(" src1: "); - src1 = atom_get_src(ctx, attr, ptr); + src1 = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr); SDEBUG(" src2: "); - src2 = atom_get_src(ctx, attr, ptr); + src2 = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr); dst &= src1; dst |= src2; SDEBUG(" dst: "); @@ -809,6 +835,38 @@ static void atom_op_setregblock(atom_exec_context *ctx, int *ptr, int arg) SDEBUG(" base: 0x%04X\n", ctx->ctx->reg_block); } +static void atom_op_shift_left(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++), shift; + uint32_t saved, dst; + int dptr = *ptr; + attr &= 0x38; + attr |= atom_def_dst[attr >> 3] << 6; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr); + SDEBUG(" shift: %d\n", shift); + dst <<= shift; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + +static void atom_op_shift_right(atom_exec_context *ctx, int *ptr, int arg) +{ + uint8_t attr = U8((*ptr)++), shift; + uint32_t saved, dst; + int dptr = *ptr; + attr &= 0x38; + attr |= atom_def_dst[attr >> 3] << 6; + SDEBUG(" dst: "); + dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); + shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr); + SDEBUG(" shift: %d\n", shift); + dst >>= shift; + SDEBUG(" dst: "); + atom_put_dst(ctx, arg, attr, &dptr, dst, saved); +} + static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg) { uint8_t attr = U8((*ptr)++), shift; @@ -818,7 +876,7 @@ static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg) attr |= atom_def_dst[attr >> 3] << 6; SDEBUG(" dst: "); dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); - shift = U8((*ptr)++); + shift = atom_get_src(ctx, attr, ptr); SDEBUG(" shift: %d\n", shift); dst <<= shift; SDEBUG(" dst: "); @@ -834,7 +892,7 @@ static void atom_op_shr(atom_exec_context *ctx, int *ptr, int arg) attr |= atom_def_dst[attr >> 3] << 6; SDEBUG(" dst: "); dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); - shift = U8((*ptr)++); + shift = atom_get_src(ctx, attr, ptr); SDEBUG(" shift: %d\n", shift); dst >>= shift; SDEBUG(" dst: "); @@ -937,18 +995,18 @@ static struct { atom_op_or, ATOM_ARG_FB}, { atom_op_or, ATOM_ARG_PLL}, { atom_op_or, ATOM_ARG_MC}, { - atom_op_shl, ATOM_ARG_REG}, { - atom_op_shl, ATOM_ARG_PS}, { - atom_op_shl, ATOM_ARG_WS}, { - atom_op_shl, ATOM_ARG_FB}, { - atom_op_shl, ATOM_ARG_PLL}, { - atom_op_shl, ATOM_ARG_MC}, { - atom_op_shr, ATOM_ARG_REG}, { - atom_op_shr, ATOM_ARG_PS}, { - atom_op_shr, ATOM_ARG_WS}, { - atom_op_shr, ATOM_ARG_FB}, { - atom_op_shr, ATOM_ARG_PLL}, { - atom_op_shr, ATOM_ARG_MC}, { + atom_op_shift_left, ATOM_ARG_REG}, { + atom_op_shift_left, ATOM_ARG_PS}, { + atom_op_shift_left, ATOM_ARG_WS}, { + atom_op_shift_left, ATOM_ARG_FB}, { + atom_op_shift_left, ATOM_ARG_PLL}, { + atom_op_shift_left, ATOM_ARG_MC}, { + atom_op_shift_right, ATOM_ARG_REG}, { + atom_op_shift_right, ATOM_ARG_PS}, { + atom_op_shift_right, ATOM_ARG_WS}, { + atom_op_shift_right, ATOM_ARG_FB}, { + atom_op_shift_right, ATOM_ARG_PLL}, { + atom_op_shift_right, ATOM_ARG_MC}, { atom_op_mul, ATOM_ARG_REG}, { atom_op_mul, ATOM_ARG_PS}, { atom_op_mul, ATOM_ARG_WS}, { -- cgit v1.2.3-70-g09d2 From e2f8e87089427d3a203538dc73058b90e82b11f6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 19 Jan 2010 12:45:29 -0500 Subject: drm/radeon/kms/atom: upstream parser updates Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atom.c | 8 +++++++- drivers/gpu/drm/radeon/atom.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 9a3378184e1..cf3126108a4 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -246,6 +246,9 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr, case ATOM_WS_ATTRIBUTES: val = gctx->io_attr; break; + case ATOM_WS_REGPTR: + val = gctx->reg_block; + break; default: val = ctx->ws[idx]; } @@ -508,6 +511,9 @@ static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr, case ATOM_WS_ATTRIBUTES: gctx->io_attr = val; break; + case ATOM_WS_REGPTR: + gctx->reg_block = val; + break; default: ctx->ws[idx] = val; } @@ -705,7 +711,7 @@ static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg) SDEBUG(" src1: "); src1 = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr); SDEBUG(" src2: "); - src2 = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr); + src2 = atom_get_src(ctx, attr, ptr); dst &= src1; dst |= src2; SDEBUG(" dst: "); diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h index 47fd943f6d1..bc73781423a 100644 --- a/drivers/gpu/drm/radeon/atom.h +++ b/drivers/gpu/drm/radeon/atom.h @@ -91,6 +91,7 @@ #define ATOM_WS_AND_MASK 0x45 #define ATOM_WS_FB_WINDOW 0x46 #define ATOM_WS_ATTRIBUTES 0x47 +#define ATOM_WS_REGPTR 0x48 #define ATOM_IIO_NOP 0 #define ATOM_IIO_START 1 -- cgit v1.2.3-70-g09d2 From 54f088a9603dbee88809cb2ddfd8dc1ef8a74be5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 19 Jan 2010 16:34:01 -0500 Subject: drm/radeon/kms: fix atombios_crtc_set_base Make it call the proper backend depending on the GPU family. Right now r4xx cards with atombios modesetting enabled were using the avivo crtc base code. This also allows us to add support for new asics more easily. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 260fcf59f00..a60610271af 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -575,8 +575,8 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } -int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) +static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; @@ -706,6 +706,18 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, return 0; } +int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + + if (ASIC_IS_AVIVO(rdev)) + return avivo_crtc_set_base(crtc, x, y, old_fb); + else + return radeon_crtc_set_base(crtc, x, y, old_fb); +} + int atombios_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -727,7 +739,7 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, else { if (radeon_crtc->crtc_id == 0) atombios_set_crtc_dtd_timing(crtc, adjusted_mode); - radeon_crtc_set_base(crtc, x, y, old_fb); + atombios_crtc_set_base(crtc, x, y, old_fb); radeon_legacy_atom_set_surface(crtc); } atombios_overscan_setup(crtc, mode, adjusted_mode); -- cgit v1.2.3-70-g09d2 From 615e0cb67968c94fd9e53797985843a5b816dec4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 20 Jan 2010 16:22:53 -0500 Subject: drm/radeon/kms/r4xx: cleanup atom path most of radeon_legacy_atom_set_surface() is taken care of in atombios_set_base(), so remove the duplicate setup and move the remaining bits (DISP_MERGE setup and FP2 sync) to atombios_crtc.c where they are used. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 26 +++++++++++- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 63 ----------------------------- drivers/gpu/drm/radeon/radeon_mode.h | 1 - 3 files changed, 25 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index a60610271af..e098bd0cbd2 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -718,6 +718,30 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, return radeon_crtc_set_base(crtc, x, y, old_fb); } +/* properly set additional regs when using atombios */ +static void radeon_legacy_atom_fixup(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + u32 disp_merge_cntl; + + switch (radeon_crtc->crtc_id) { + case 0: + disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL); + disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; + WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl); + break; + case 1: + disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); + disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; + WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl); + WREG32(RADEON_FP_H2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_H_SYNC_STRT_WID)); + WREG32(RADEON_FP_V2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_V_SYNC_STRT_WID)); + break; + } +} + int atombios_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -740,7 +764,7 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, if (radeon_crtc->crtc_id == 0) atombios_set_crtc_dtd_timing(crtc, adjusted_mode); atombios_crtc_set_base(crtc, x, y, old_fb); - radeon_legacy_atom_set_surface(crtc); + radeon_legacy_atom_fixup(crtc); } atombios_overscan_setup(crtc, mode, adjusted_mode); atombios_scaler_setup(crtc); diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index cc27485a07a..762e07b0895 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -339,69 +339,6 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) } } -/* properly set crtc bpp when using atombios */ -void radeon_legacy_atom_set_surface(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - int format; - uint32_t crtc_gen_cntl; - uint32_t disp_merge_cntl; - uint32_t crtc_pitch; - - switch (crtc->fb->bits_per_pixel) { - case 8: - format = 2; - break; - case 15: /* 555 */ - format = 3; - break; - case 16: /* 565 */ - format = 4; - break; - case 24: /* RGB */ - format = 5; - break; - case 32: /* xRGB */ - format = 6; - break; - default: - return; - } - - crtc_pitch = ((((crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8)) * crtc->fb->bits_per_pixel) + - ((crtc->fb->bits_per_pixel * 8) - 1)) / - (crtc->fb->bits_per_pixel * 8)); - crtc_pitch |= crtc_pitch << 16; - - WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch); - - switch (radeon_crtc->crtc_id) { - case 0: - disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL); - disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; - WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl); - - crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff; - crtc_gen_cntl |= (format << 8); - crtc_gen_cntl |= RADEON_CRTC_EXT_DISP_EN; - WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); - break; - case 1: - disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); - disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; - WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl); - - crtc_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff; - crtc_gen_cntl |= (format << 8); - WREG32(RADEON_CRTC2_GEN_CNTL, crtc_gen_cntl); - WREG32(RADEON_FP_H2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_H_SYNC_STRT_WID)); - WREG32(RADEON_FP_V2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_V_SYNC_STRT_WID)); - break; - } -} - int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 91cb041cb40..eb19b3022b0 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -453,7 +453,6 @@ extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode); extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb); -extern void radeon_legacy_atom_set_surface(struct drm_crtc *crtc); extern int radeon_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, -- cgit v1.2.3-70-g09d2 From 0c45249f419d8b86abe0e51c6627ca4b085e8c23 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 15 Jan 2010 14:44:37 +0100 Subject: drm/radeon/kms: r600/r700 disable irq at suspend To avoid hw doing anythings after we disabled PCIE GART, fully disable IRQ at suspend. Also cleanup a bit the ih structure and process function. Signed-off-by: Jerome Glisse Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 30 ++++++++++++++---------------- drivers/gpu/drm/radeon/radeon.h | 4 ++-- drivers/gpu/drm/radeon/rv770.c | 1 + 3 files changed, 17 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index b3713f61964..a6a23a9f9a5 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1954,6 +1954,7 @@ int r600_suspend(struct radeon_device *rdev) /* FIXME: we should wait for ring to be empty */ r600_cp_stop(rdev); rdev->cp.ready = false; + r600_irq_suspend(rdev); r600_wb_disable(rdev); r600_pcie_gart_disable(rdev); /* unpin shaders bo */ @@ -2200,14 +2201,14 @@ void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size) rb_bufsz = drm_order(ring_size / 4); ring_size = (1 << rb_bufsz) * 4; rdev->ih.ring_size = ring_size; - rdev->ih.align_mask = 4 - 1; + rdev->ih.ptr_mask = rdev->ih.ring_size - 1; + rdev->ih.rptr = 0; } -static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size) +static int r600_ih_ring_alloc(struct radeon_device *rdev) { int r; - rdev->ih.ring_size = ring_size; /* Allocate ring buffer */ if (rdev->ih.ring_obj == NULL) { r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size, @@ -2237,9 +2238,6 @@ static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size) return r; } } - rdev->ih.ptr_mask = (rdev->cp.ring_size / 4) - 1; - rdev->ih.rptr = 0; - return 0; } @@ -2389,7 +2387,7 @@ int r600_irq_init(struct radeon_device *rdev) u32 interrupt_cntl, ih_cntl, ih_rb_cntl; /* allocate ring */ - ret = r600_ih_ring_alloc(rdev, rdev->ih.ring_size); + ret = r600_ih_ring_alloc(rdev); if (ret) return ret; @@ -2452,10 +2450,15 @@ int r600_irq_init(struct radeon_device *rdev) return ret; } -void r600_irq_fini(struct radeon_device *rdev) +void r600_irq_suspend(struct radeon_device *rdev) { r600_disable_interrupts(rdev); r600_rlc_stop(rdev); +} + +void r600_irq_fini(struct radeon_device *rdev) +{ + r600_irq_suspend(rdev); r600_ih_ring_fini(rdev); } @@ -2648,9 +2651,7 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) tmp |= IH_WPTR_OVERFLOW_CLEAR; WREG32(IH_RB_CNTL, tmp); } - wptr = wptr & WPTR_OFFSET_MASK; - - return wptr; + return (wptr & rdev->ih.ptr_mask); } /* r600 IV Ring @@ -2686,7 +2687,6 @@ int r600_irq_process(struct radeon_device *rdev) u32 wptr = r600_get_ih_wptr(rdev); u32 rptr = rdev->ih.rptr; u32 src_id, src_data; - u32 last_entry = rdev->ih.ring_size - 16; u32 ring_index, disp_int, disp_int_cont, disp_int_cont2; unsigned long flags; bool queue_hotplug = false; @@ -2820,10 +2820,8 @@ restart_ih: } /* wptr/rptr are in bytes! */ - if (rptr == last_entry) - rptr = 0; - else - rptr += 16; + rptr += 16; + rptr &= rdev->ih.ptr_mask; } /* make sure wptr hasn't changed while processing */ wptr = r600_get_ih_wptr(rdev); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index c23278240a4..09c655f3843 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -410,7 +410,6 @@ struct r600_ih { unsigned wptr_old; unsigned ring_size; uint64_t gpu_addr; - uint32_t align_mask; uint32_t ptr_mask; spinlock_t lock; bool enabled; @@ -1162,7 +1161,8 @@ extern int r600_irq_init(struct radeon_device *rdev); extern void r600_irq_fini(struct radeon_device *rdev); extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size); extern int r600_irq_set(struct radeon_device *rdev); - +extern void r600_irq_suspend(struct radeon_device *rdev); +/* r600 audio */ extern int r600_audio_init(struct radeon_device *rdev); extern int r600_audio_tmds_index(struct drm_encoder *encoder); extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index eb065bbe1ee..c8cf2bc2b91 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -968,6 +968,7 @@ int rv770_suspend(struct radeon_device *rdev) /* FIXME: we should wait for ring to be empty */ r700_cp_stop(rdev); rdev->cp.ready = false; + r600_irq_suspend(rdev); r600_wb_disable(rdev); rv770_pcie_gart_disable(rdev); /* unpin shaders bo */ -- cgit v1.2.3-70-g09d2 From 79c2bbc505751bb5130ac753251fc9a0eb37bb12 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 15 Jan 2010 14:44:38 +0100 Subject: drm/radeon/kms: r600/r700 don't process IRQ if not initialized In some rare case the wptr returned from the hw wasn't 0 and leaded to trick r600_process_irq that their were irq to process. Add a check to bail out if irq hasn't been initialized this will avoid oops provoqued by the rare wptr != 0 on initialization. Signed-off-by: Jerome Glisse Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index a6a23a9f9a5..0f9a8c6788a 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2473,8 +2473,12 @@ int r600_irq_set(struct radeon_device *rdev) return -EINVAL; } /* don't enable anything if the ih is disabled */ - if (!rdev->ih.enabled) + if (!rdev->ih.enabled) { + r600_disable_interrupts(rdev); + /* force the active interrupt state to all disabled */ + r600_disable_interrupt_state(rdev); return 0; + } if (ASIC_IS_DCE3(rdev)) { hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; @@ -2692,6 +2696,8 @@ int r600_irq_process(struct radeon_device *rdev) bool queue_hotplug = false; DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + if (!rdev->ih.enabled) + return IRQ_NONE; spin_lock_irqsave(&rdev->ih.lock, flags); -- cgit v1.2.3-70-g09d2 From 7924e5eb8fe422d6b1ce3b3e2be749a480dfcdd9 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 15 Jan 2010 14:44:39 +0100 Subject: drm/radeon/kms: r600 handle irq vector ring overflow In some rare case i faced an irq overflow quickly followed by a GPU lockup (hard hang) this patch try to deal with irq vector ring overflow, so far haven't been able to reproduce it with the patch. Signed-off-by: Jerome Glisse Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 0f9a8c6788a..bb9115bdc3a 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2648,9 +2648,13 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) wptr = RREG32(IH_RB_WPTR); if (wptr & RB_OVERFLOW) { - WARN_ON(1); - /* XXX deal with overflow */ - DRM_ERROR("IH RB overflow\n"); + /* When a ring buffer overflow happen start parsing interrupt + * from the last not overwritten vector (wptr + 16). Hopefully + * this should allow us to catchup. + */ + dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n", + wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask); + rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask; tmp = RREG32(IH_RB_CNTL); tmp |= IH_WPTR_OVERFLOW_CLEAR; WREG32(IH_RB_CNTL, tmp); -- cgit v1.2.3-70-g09d2 From 7e71c9e2e7704ebf044d4a964e02fbd2098a173f Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Sun, 17 Jan 2010 21:21:41 +0100 Subject: drm/radeon/kms: Forbid creation of framebuffer with no valid GEM object This will avoid oops if at later point the fb is use. Trying to create a framebuffer with no valid GEM object is bogus and should be forbidden as this patch does. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_display.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 49f3c69cf24..f899320f0a6 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -715,7 +715,11 @@ radeon_user_framebuffer_create(struct drm_device *dev, struct drm_gem_object *obj; obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); - + if (obj == NULL) { + dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, " + "can't create framebuffer\n", mode_cmd->handle); + return NULL; + } return radeon_framebuffer_create(dev, mode_cmd, obj); } -- cgit v1.2.3-70-g09d2 From db96380ea26fcc31ab37189aedeabd12894b1431 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Sun, 17 Jan 2010 21:21:56 +0100 Subject: drm/radeon/kms: r600/r700 don't test ib if ib initialization fails If ib initialization failed don't try to test ib as it will result in an oops (accessing NULL ib buffer ptr). Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 13 +++++++------ drivers/gpu/drm/radeon/rv770.c | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index bb9115bdc3a..d0bd117a463 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2064,13 +2064,14 @@ int r600_init(struct radeon_device *rdev) if (rdev->accel_working) { r = radeon_ib_pool_init(rdev); if (r) { - DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); - rdev->accel_working = false; - } - r = r600_ib_test(rdev); - if (r) { - DRM_ERROR("radeon: failed testing IB (%d).\n", r); + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); rdev->accel_working = false; + } else { + r = r600_ib_test(rdev); + if (r) { + dev_err(rdev->dev, "IB test failed (%d).\n", r); + rdev->accel_working = false; + } } } diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index c8cf2bc2b91..cf8f2b17d62 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1075,13 +1075,14 @@ int rv770_init(struct radeon_device *rdev) if (rdev->accel_working) { r = radeon_ib_pool_init(rdev); if (r) { - DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); - rdev->accel_working = false; - } - r = r600_ib_test(rdev); - if (r) { - DRM_ERROR("radeon: failed testing IB (%d).\n", r); + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); rdev->accel_working = false; + } else { + r = r600_ib_test(rdev); + if (r) { + dev_err(rdev->dev, "IB test failed (%d).\n", r); + rdev->accel_working = false; + } } } return 0; -- cgit v1.2.3-70-g09d2 From c8c15ff1e90bfc4a2db1ba77a01b3b2783e723fc Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Mon, 18 Jan 2010 13:01:36 +0100 Subject: drm/radeon: r6xx/r7xx possible security issue, system ram access This patch workaround a possible security issue which can allow user to abuse drm on r6xx/r7xx hw to access any system ram memory. This patch doesn't break userspace, it detect "valid" old use of CB_COLOR[0-7]_FRAG & CB_COLOR[0-7]_TILE registers and overwritte the address these registers are pointing to with the one of the last color buffer. This workaround will work for old mesa & xf86-video-ati and any old user which did use similar register programming pattern as those (we expect that there is no others user of those ioctl except possibly a malicious one). This patch add a warning if it detects such usage, warning encourage people to update their mesa & xf86-video-ati. New userspace will submit proper relocation. Fix for xf86-video-ati / mesa (this kernel patch is enough to prevent abuse, fix for userspace are to set proper cs stream and avoid kernel warning) : http://cgit.freedesktop.org/xorg/driver/xf86-video-ati/commit/?id=95d63e408cc88b6934bec84a0b1ef94dfe8bee7b http://cgit.freedesktop.org/mesa/mesa/commit/?id=46dc6fd3ed5ef96cda53641a97bc68c3bc104a9f Abusing this register to perform system ram memory is not easy, here is outline on how it could be achieve. First attacker must have access to the drm device and be able to submit command stream throught cs ioctl. Then attacker must build a proper command stream for r6xx/r7xx hw which will abuse the FRAG or TILE buffer to overwrite the GPU GART which is in VRAM. To achieve so attacker as to setup CB_COLOR[0-7]_FRAG or CB_COLOR[0-7]_TILE to point to the GPU GART, then it has to find a way to write predictable value into those buffer (with little cleverness i believe this can be done but this is an hard task). Once attacker have such program it can overwritte GPU GART to program GPU gart to point anywhere in system memory. It then can reusse same method as he used to reprogram GART to overwritte the system ram through the GART mapping. In the process the attacker has to be carefull to not overwritte any sensitive area of the GART table, like ring or IB gart entry as it will more then likely lead to GPU lockup. Bottom line is that i think it's very hard to use this flaw to get system ram access but in theory one can achieve so. Side note: I am not aware of anyone ever using the GPU as an attack vector, nevertheless we take great care in the opensource driver to try to detect and forbid malicious use of GPU. I don't think the closed source driver are as cautious as we are. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600_cs.c | 83 ++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/r600d.h | 25 ++++++++++++ drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_cs.c | 1 + 4 files changed, 110 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 44060b92d9e..9cc4ba8d03d 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -36,6 +36,10 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**); static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm; +struct r600_cs_track { + u32 cb_color0_base_last; +}; + /** * r600_cs_packet_parse() - parse cp packet and point ib index to next packet * @parser: parser structure holding parsing context. @@ -176,6 +180,28 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, return 0; } +/** + * r600_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc + * @parser: parser structure holding parsing context. + * + * Check next packet is relocation packet3, do bo validation and compute + * GPU offset using the provided start. + **/ +static inline int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p) +{ + struct radeon_cs_packet p3reloc; + int r; + + r = r600_cs_packet_parse(p, &p3reloc, p->idx); + if (r) { + return 0; + } + if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { + return 0; + } + return 1; +} + /** * r600_cs_packet_next_vline() - parse userspace VLINE packet * @parser: parser structure holding parsing context. @@ -337,6 +363,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { struct radeon_cs_reloc *reloc; + struct r600_cs_track *track; volatile u32 *ib; unsigned idx; unsigned i; @@ -344,6 +371,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, int r; u32 idx_value; + track = (struct r600_cs_track *)p->track; ib = p->ib->ptr; idx = pkt->idx + 1; idx_value = radeon_get_ib_value(p, idx); @@ -503,9 +531,60 @@ static int r600_packet3_check(struct radeon_cs_parser *p, for (i = 0; i < pkt->count; i++) { reg = start_reg + (4 * i); switch (reg) { + /* This register were added late, there is userspace + * which does provide relocation for those but set + * 0 offset. In order to avoid breaking old userspace + * we detect this and set address to point to last + * CB_COLOR0_BASE, note that if userspace doesn't set + * CB_COLOR0_BASE before this register we will report + * error. Old userspace always set CB_COLOR0_BASE + * before any of this. + */ + case R_0280E0_CB_COLOR0_FRAG: + case R_0280E4_CB_COLOR1_FRAG: + case R_0280E8_CB_COLOR2_FRAG: + case R_0280EC_CB_COLOR3_FRAG: + case R_0280F0_CB_COLOR4_FRAG: + case R_0280F4_CB_COLOR5_FRAG: + case R_0280F8_CB_COLOR6_FRAG: + case R_0280FC_CB_COLOR7_FRAG: + case R_0280C0_CB_COLOR0_TILE: + case R_0280C4_CB_COLOR1_TILE: + case R_0280C8_CB_COLOR2_TILE: + case R_0280CC_CB_COLOR3_TILE: + case R_0280D0_CB_COLOR4_TILE: + case R_0280D4_CB_COLOR5_TILE: + case R_0280D8_CB_COLOR6_TILE: + case R_0280DC_CB_COLOR7_TILE: + if (!r600_cs_packet_next_is_pkt3_nop(p)) { + if (!track->cb_color0_base_last) { + dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); + return -EINVAL; + } + ib[idx+1+i] = track->cb_color0_base_last; + printk_once(KERN_WARNING "You have old & broken userspace " + "please consider updating mesa & xf86-video-ati\n"); + } else { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); + return -EINVAL; + } + ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + } + break; case DB_DEPTH_BASE: case DB_HTILE_DATA_BASE: case CB_COLOR0_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->cb_color0_base_last = ib[idx+1+i]; + break; case CB_COLOR1_BASE: case CB_COLOR2_BASE: case CB_COLOR3_BASE: @@ -678,8 +757,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p, int r600_cs_parse(struct radeon_cs_parser *p) { struct radeon_cs_packet pkt; + struct r600_cs_track *track; int r; + track = kzalloc(sizeof(*track), GFP_KERNEL); + p->track = track; do { r = r600_cs_packet_parse(p, &pkt, p->idx); if (r) { @@ -757,6 +839,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp, /* initialize parser */ memset(&parser, 0, sizeof(struct radeon_cs_parser)); parser.filp = filp; + parser.dev = &dev->pdev->dev; parser.rdev = NULL; parser.family = family; parser.ib = &fake_ib; diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 05894edadab..30480881aed 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -882,4 +882,29 @@ #define S_000E60_SOFT_RESET_VMC(x) (((x) & 1) << 17) #define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 + +#define R_0280E0_CB_COLOR0_FRAG 0x0280E0 +#define S_0280E0_BASE_256B(x) (((x) & 0xFFFFFFFF) << 0) +#define G_0280E0_BASE_256B(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_0280E0_BASE_256B 0x00000000 +#define R_0280E4_CB_COLOR1_FRAG 0x0280E4 +#define R_0280E8_CB_COLOR2_FRAG 0x0280E8 +#define R_0280EC_CB_COLOR3_FRAG 0x0280EC +#define R_0280F0_CB_COLOR4_FRAG 0x0280F0 +#define R_0280F4_CB_COLOR5_FRAG 0x0280F4 +#define R_0280F8_CB_COLOR6_FRAG 0x0280F8 +#define R_0280FC_CB_COLOR7_FRAG 0x0280FC +#define R_0280C0_CB_COLOR0_TILE 0x0280C0 +#define S_0280C0_BASE_256B(x) (((x) & 0xFFFFFFFF) << 0) +#define G_0280C0_BASE_256B(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_0280C0_BASE_256B 0x00000000 +#define R_0280C4_CB_COLOR1_TILE 0x0280C4 +#define R_0280C8_CB_COLOR2_TILE 0x0280C8 +#define R_0280CC_CB_COLOR3_TILE 0x0280CC +#define R_0280D0_CB_COLOR4_TILE 0x0280D0 +#define R_0280D4_CB_COLOR5_TILE 0x0280D4 +#define R_0280D8_CB_COLOR6_TILE 0x0280D8 +#define R_0280DC_CB_COLOR7_TILE 0x0280DC + + #endif diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 09c655f3843..f7df1a7e441 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -464,6 +464,7 @@ struct radeon_cs_chunk { }; struct radeon_cs_parser { + struct device *dev; struct radeon_device *rdev; struct drm_file *filp; /* chunks */ diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 65590a0f1d9..1496cb8658e 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -231,6 +231,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) memset(&parser, 0, sizeof(struct radeon_cs_parser)); parser.filp = filp; parser.rdev = rdev; + parser.dev = rdev->dev; r = radeon_cs_parser_init(&parser, data); if (r) { DRM_ERROR("Failed to initialize parser !\n"); -- cgit v1.2.3-70-g09d2 From f776c5ec4690b21b3668ad5956774a22c86f541a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 18 Jan 2010 14:36:12 +0100 Subject: driver-core: fix devtmpfs crash on s390 On Mon, Jan 18, 2010 at 05:26:20PM +0530, Sachin Sant wrote: > Hello Heiko, > > Today while trying to boot next-20100118 i came across > the following Oops : > > Brought up 4 CPUs > Unable to handle kernel pointer dereference at virtual kernel address 0000000000 > 543000 > Oops: 0004 #1 SMP > Modules linked in: > CPU: 0 Not tainted 2.6.33-rc4-autotest-next-20100118-5-default #1 > Process swapper (pid: 1, task: 00000000fd792038, ksp: 00000000fd797a30) > Krnl PSW : 0704200180000000 00000000001eb0b8 (shmem_parse_options+0xc0/0x328) > R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:2 PM:0 EA:3 > Krnl GPRS: 000000000054388a 000000000000003d 0000000000543836 000000000000003d > 0000000000000000 0000000000483f28 0000000000536112 00000000fd797d00 > 00000000fd4ba100 0000000000000100 0000000000483978 0000000000543832 > 0000000000000000 0000000000465958 00000000001eb0b0 00000000fd797c58 > Krnl Code: 00000000001eb0aa: c0e5000994f1 brasl %r14,31da8c > 00000000001eb0b0: b9020022 ltgr %r2,%r2 > 00000000001eb0b4: a784010b brc 8,1eb2ca > >00000000001eb0b8: 92002000 mvi 0(%r2),0 > 00000000001eb0bc: a7080000 lhi %r0,0 > 00000000001eb0c0: 41902001 la %r9,1(%r2) > 00000000001eb0c4: b9040016 lgr %r1,%r6 > 00000000001eb0c8: b904002b lgr %r2,%r11 > Call Trace: > (<00000000fd797c50> 0xfd797c50) > <00000000001eb5da> shmem_fill_super+0x13a/0x25c > <0000000000228cfa> get_sb_single+0xbe/0xdc > <000000000034ffc0> dev_get_sb+0x2c/0x38 > <000000000066c602> devtmpfs_init+0x46/0xc0 > <000000000066c53e> driver_init+0x22/0x60 > <000000000064d40a> kernel_init+0x24e/0x3d0 > <000000000010a7ea> kernel_thread_starter+0x6/0xc > <000000000010a7e4> kernel_thread_starter+0x0/0xc > > I never tried to boot a kernel with DEVTMPFS enabled on a s390 box. > So am wondering if this is supported or not ? If you think this > is supported i will send a mail to community on this. There is nothing arch specific to devtmpfs. This part crashes because the kernel tries to modify the data read-only section which is write protected on s390. Signed-off-by: Heiko Carstens Acked-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 090dd485130..42ae452b36b 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -354,6 +354,7 @@ int __init devtmpfs_init(void) { int err; struct vfsmount *mnt; + char options[] = "mode=0755"; err = register_filesystem(&dev_fs_type); if (err) { @@ -362,7 +363,7 @@ int __init devtmpfs_init(void) return err; } - mnt = kern_mount_data(&dev_fs_type, "mode=0755"); + mnt = kern_mount_data(&dev_fs_type, options); if (IS_ERR(mnt)) { err = PTR_ERR(mnt); printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err); -- cgit v1.2.3-70-g09d2 From bd796671f093d5b1841d383674d5650f5ec6c9c6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 19 Jan 2010 13:08:16 -0800 Subject: Revert "sysdev: fix prototype for memory_sysdev_class show/store functions" This reverts commit 8ff410daa009c4b44be445ded5b0cec00abc0426 It should not have been sent to Linus's tree yet, as it depends on changes that are queued up in my driver-core for the .34 kernel merge. Cc: Wu Fengguang Cc: Andi Kleen Cc: "Zheng, Shaohui" Cc: Andrew Morton Cc: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/base/memory.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/base/memory.c b/drivers/base/memory.c index ae6b6c43cff..bd025059711 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -309,19 +309,17 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); * Block size attribute stuff */ static ssize_t -print_block_size(struct sysdev_class *class, - struct sysdev_class_attribute *class_attr, - char *buf) +print_block_size(struct class *class, char *buf) { return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); } -static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); +static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); static int block_size_init(void) { return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &attr_block_size_bytes.attr); + &class_attr_block_size_bytes.attr); } /* @@ -332,9 +330,7 @@ static int block_size_init(void) */ #ifdef CONFIG_ARCH_MEMORY_PROBE static ssize_t -memory_probe_store(struct sysdev_class *class, - struct sysdev_class_attribute *class_attr, - const char *buf, size_t count) +memory_probe_store(struct class *class, const char *buf, size_t count) { u64 phys_addr; int nid; @@ -350,12 +346,12 @@ memory_probe_store(struct sysdev_class *class, return count; } -static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); +static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); static int memory_probe_init(void) { return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &attr_probe.attr); + &class_attr_probe.attr); } #else static inline int memory_probe_init(void) @@ -371,9 +367,7 @@ static inline int memory_probe_init(void) /* Soft offline a page */ static ssize_t -store_soft_offline_page(struct sysdev_class *class, - struct sysdev_class_attribute *class_attr, - const char *buf, size_t count) +store_soft_offline_page(struct class *class, const char *buf, size_t count) { int ret; u64 pfn; @@ -390,9 +384,7 @@ store_soft_offline_page(struct sysdev_class *class, /* Forcibly offline a page, including killing processes. */ static ssize_t -store_hard_offline_page(struct sysdev_class *class, - struct sysdev_class_attribute *class_attr, - const char *buf, size_t count) +store_hard_offline_page(struct class *class, const char *buf, size_t count) { int ret; u64 pfn; @@ -405,18 +397,18 @@ store_hard_offline_page(struct sysdev_class *class, return ret ? ret : count; } -static SYSDEV_CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); -static SYSDEV_CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page); +static CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); +static CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page); static __init int memory_fail_init(void) { int err; err = sysfs_create_file(&memory_sysdev_class.kset.kobj, - &attr_soft_offline_page.attr); + &class_attr_soft_offline_page.attr); if (!err) err = sysfs_create_file(&memory_sysdev_class.kset.kobj, - &attr_hard_offline_page.attr); + &class_attr_hard_offline_page.attr); return err; } #else -- cgit v1.2.3-70-g09d2 From eeec32a731631a9bad9abb21c626b9f2840bee0d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 4 Jan 2010 16:26:50 +0000 Subject: nozomi: quick fix for the close/close bug Nozomi goes wrong if you get the sequence open open close [stuff] close which turns out to occur on some ppp type setups. This is a quick patch up for the problem. It's not really fixing Nozomi which completely fails to implement tty open/close semantics and all the other needed stuff. Doing it right is a rather more invasive patch set and not one that will backport. Signed-off-by: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/char/nozomi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 7d73cd43034..2ad7d37afbd 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -1651,10 +1651,10 @@ static void ntty_close(struct tty_struct *tty, struct file *file) dc->open_ttys--; port->count--; - tty_port_tty_set(port, NULL); if (port->count == 0) { DBG1("close: %d", nport->token_dl); + tty_port_tty_set(port, NULL); spin_lock_irqsave(&dc->spin_mutex, flags); dc->last_ier &= ~(nport->token_dl); writew(dc->last_ier, dc->reg_ier); -- cgit v1.2.3-70-g09d2 From 6d34855d9aa281f72c533ecb827405139d1b0fe9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 9 Dec 2009 12:31:37 -0800 Subject: serial: 8250_pnp: use wildcard for serial Wacom tablets Wacom claims that the WACF namespace will always be devoted to serial Wacom tablets. Remove the existing entries and add a wildcard to avoid having to update the kernel every time they add a new device. Signed-off-by: Ping Cheng Signed-off-by: Matthew Garrett Tested-by: Ping Cheng Cc: Alan Cox Signed-off-by: Andrew Morton Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250_pnp.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index b5496a19d96..24485cc62ff 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -328,15 +328,7 @@ static const struct pnp_device_id pnp_dev_table[] = { /* U.S. Robotics 56K Voice INT PnP*/ { "USR9190", 0 }, /* Wacom tablets */ - { "WACF004", 0 }, - { "WACF005", 0 }, - { "WACF006", 0 }, - { "WACF007", 0 }, - { "WACF008", 0 }, - { "WACF009", 0 }, - { "WACF00A", 0 }, - { "WACF00B", 0 }, - { "WACF00C", 0 }, + { "WACFXXX", 0 }, /* Compaq touchscreen */ { "FPI2002", 0 }, /* Fujitsu Stylistic touchscreens */ -- cgit v1.2.3-70-g09d2 From 4547be7809a3b775ce750ec7f8b5748954741523 Mon Sep 17 00:00:00 2001 From: Stanislav Brabec Date: Wed, 2 Dec 2009 16:20:56 +0100 Subject: serial-core: resume serial hardware with no_console_suspend Perform a tricky suspend/resume even with no_console_suspend. With no_console_suspend, kernel skips serial port suspend/resume and the serial hardware may remain in undefined state after resume. It actually happens on devices that don't have BIOS that handle serial initialization. It makes impossible to use serial console after resume. Devices affected by this problem include: Sharp Zaurus devices Several PXA based ARM embedded boards The patch does: - Save the hardware state - Perform buffer flush in time of its suspend call - Tell the driver that port is suspended - But still accept new data - And keep console hardware in state that allows to send them It allows to capture late console messages without breaking console after resume. This is just a resend of a patch discussed in these threads, as the patch was not yet applied. "Possible suspend/resume regression in .32-rc?" (Nov 1-5, 2009, ARM list, later LKML) "serial-core: resume serial hardware with no_console_suspend" (Sep 15-Oct 18, 2009, LKML & ARM lists) Signed-off-by: Stanislav Brabec Tested-by: Haojian Zhuang Tested-by: Daniel Mack Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 88 +++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 047530b285b..fa4f170f2e8 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -2006,12 +2006,6 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) mutex_lock(&port->mutex); - if (!console_suspend_enabled && uart_console(uport)) { - /* we're going to avoid suspending serial console */ - mutex_unlock(&port->mutex); - return 0; - } - tty_dev = device_find_child(uport->dev, &match, serial_match_port); if (device_may_wakeup(tty_dev)) { enable_irq_wake(uport->irq); @@ -2019,20 +2013,23 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) mutex_unlock(&port->mutex); return 0; } - uport->suspended = 1; + if (console_suspend_enabled || !uart_console(uport)) + uport->suspended = 1; if (port->flags & ASYNC_INITIALIZED) { const struct uart_ops *ops = uport->ops; int tries; - set_bit(ASYNCB_SUSPENDED, &port->flags); - clear_bit(ASYNCB_INITIALIZED, &port->flags); + if (console_suspend_enabled || !uart_console(uport)) { + set_bit(ASYNCB_SUSPENDED, &port->flags); + clear_bit(ASYNCB_INITIALIZED, &port->flags); - spin_lock_irq(&uport->lock); - ops->stop_tx(uport); - ops->set_mctrl(uport, 0); - ops->stop_rx(uport); - spin_unlock_irq(&uport->lock); + spin_lock_irq(&uport->lock); + ops->stop_tx(uport); + ops->set_mctrl(uport, 0); + ops->stop_rx(uport); + spin_unlock_irq(&uport->lock); + } /* * Wait for the transmitter to empty. @@ -2047,16 +2044,18 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) drv->dev_name, drv->tty_driver->name_base + uport->line); - ops->shutdown(uport); + if (console_suspend_enabled || !uart_console(uport)) + ops->shutdown(uport); } /* * Disable the console device before suspending. */ - if (uart_console(uport)) + if (console_suspend_enabled && uart_console(uport)) console_stop(uport->cons); - uart_change_pm(state, 3); + if (console_suspend_enabled || !uart_console(uport)) + uart_change_pm(state, 3); mutex_unlock(&port->mutex); @@ -2073,29 +2072,6 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) mutex_lock(&port->mutex); - if (!console_suspend_enabled && uart_console(uport)) { - /* no need to resume serial console, it wasn't suspended */ - /* - * First try to use the console cflag setting. - */ - memset(&termios, 0, sizeof(struct ktermios)); - termios.c_cflag = uport->cons->cflag; - /* - * If that's unset, use the tty termios setting. - */ - if (termios.c_cflag == 0) - termios = *state->port.tty->termios; - else { - termios.c_ispeed = termios.c_ospeed = - tty_termios_input_baud_rate(&termios); - termios.c_ispeed = termios.c_ospeed = - tty_termios_baud_rate(&termios); - } - uport->ops->set_termios(uport, &termios, NULL); - mutex_unlock(&port->mutex); - return 0; - } - tty_dev = device_find_child(uport->dev, &match, serial_match_port); if (!uport->suspended && device_may_wakeup(tty_dev)) { disable_irq_wake(uport->irq); @@ -2121,21 +2097,23 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) spin_lock_irq(&uport->lock); ops->set_mctrl(uport, 0); spin_unlock_irq(&uport->lock); - ret = ops->startup(uport); - if (ret == 0) { - uart_change_speed(state, NULL); - spin_lock_irq(&uport->lock); - ops->set_mctrl(uport, uport->mctrl); - ops->start_tx(uport); - spin_unlock_irq(&uport->lock); - set_bit(ASYNCB_INITIALIZED, &port->flags); - } else { - /* - * Failed to resume - maybe hardware went away? - * Clear the "initialized" flag so we won't try - * to call the low level drivers shutdown method. - */ - uart_shutdown(state); + if (console_suspend_enabled || !uart_console(uport)) { + ret = ops->startup(uport); + if (ret == 0) { + uart_change_speed(state, NULL); + spin_lock_irq(&uport->lock); + ops->set_mctrl(uport, uport->mctrl); + ops->start_tx(uport); + spin_unlock_irq(&uport->lock); + set_bit(ASYNCB_INITIALIZED, &port->flags); + } else { + /* + * Failed to resume - maybe hardware went away? + * Clear the "initialized" flag so we won't try + * to call the low level drivers shutdown method. + */ + uart_shutdown(state); + } } clear_bit(ASYNCB_SUSPENDED, &port->flags); -- cgit v1.2.3-70-g09d2 From 16ae2a877bf4179737921235e85ceffd7b79354f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 4 Jan 2010 16:26:21 +0000 Subject: serial: Fix crash if the minimum rate of the device is > 9600 baud In that situation if the old rate is invalid and the new rate is invalid and the chip cannot do 9600 baud we report zero, which makes all the drivers explode. Instead force the rate based on min/max Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index fa4f170f2e8..7f283070951 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -385,13 +385,20 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, } /* - * As a last resort, if the quotient is zero, - * default to 9600 bps + * As a last resort, if the range cannot be met then clip to + * the nearest chip supported rate. */ - if (!hung_up) - tty_termios_encode_baud_rate(termios, 9600, 9600); + if (!hung_up) { + if (baud <= min) + tty_termios_encode_baud_rate(termios, + min + 1, min + 1); + else + tty_termios_encode_baud_rate(termios, + max - 1, max - 1); + } } - + /* Should never happen */ + WARN_ON(1); return 0; } -- cgit v1.2.3-70-g09d2 From 2e2eb509aa7a333fe9931cf306fc7dbc3473f25b Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Wed, 9 Dec 2009 12:31:36 -0800 Subject: serial: imx: bit &/| confusion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since UCR1_UARTEN is defined 1, the port was always treated as enabled. Signed-off-by: Roel Kluin Cc: Alan Cox Acked-by: Oskar Schirmer Cc: Sascha Hauer Cc: Fabian Godehardt Cc: Daniel Glöckner Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 18130f11238..60d665a17a8 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -1088,7 +1088,7 @@ imx_console_get_options(struct imx_port *sport, int *baud, int *parity, int *bits) { - if ( readl(sport->port.membase + UCR1) | UCR1_UARTEN ) { + if (readl(sport->port.membase + UCR1) & UCR1_UARTEN) { /* ok, the port was enabled */ unsigned int ucr2, ubir,ubmr, uartclk; unsigned int baud_raw; -- cgit v1.2.3-70-g09d2 From 18c576f950167ff3ec1e56dcbbec7b87288b3237 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 9 Dec 2009 12:31:31 -0800 Subject: serial: serial_cs: oxsemi quirk breaks resume Quirk is applied on all cards with given manfid (is it that correct?). Unfortunately, that quirk breaks resume on zaurus with billionton bluetooth card inserted: c950ctrl is 0 and outb() faults. I believe it is simply not a multiport card. (info->multi == 1). ... ... confirmed by printks. Signed-off-by: Pavel Machek Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_cs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 0ee7239c5d6..df854401af2 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -146,7 +146,8 @@ static void quirk_wakeup_oxsemi(struct pcmcia_device *link) { struct serial_info *info = link->priv; - outb(12, info->c950ctrl + 1); + if (info->c950ctrl) + outb(12, info->c950ctrl + 1); } /* request_region? oxsemi branch does no request_region too... */ -- cgit v1.2.3-70-g09d2 From 703625118069f9f8960d356676662d3db5a9d116 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 17 Dec 2009 07:07:19 -0800 Subject: tty: fix race in tty_fasync We need to keep the lock held over the call to __f_setown() to prevent a PID race. Thanks to Al Viro for pointing out the problem, and to Travis for making us look here in the first place. Cc: Eric W. Biederman Cc: Al Viro Cc: Alan Cox Cc: Linus Torvalds Cc: Tavis Ormandy Cc: Jeff Dike Cc: Julien Tinnes Cc: Matt Mackall Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/char/tty_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f15df40bc31..c6f3b48be9d 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1951,8 +1951,8 @@ static int tty_fasync(int fd, struct file *filp, int on) pid = task_pid(current); type = PIDTYPE_PID; } - spin_unlock_irqrestore(&tty->ctrl_lock, flags); retval = __f_setown(filp, pid, type, 0); + spin_unlock_irqrestore(&tty->ctrl_lock, flags); if (retval) goto out; } else { -- cgit v1.2.3-70-g09d2 From 20633bf0141c5e93e3396770d5eb7d200ee4068a Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Wed, 23 Dec 2009 10:27:22 -0200 Subject: Staging: asus_oled: fix oops in 2.6.32.2 After updating to 2.6.32 kernel, I started experiencing Oopses caused by the asus_oled module. After quick investigation, I wrapped this simple patch which fixes an Oops in by asus_oled module on 2.6.32.2 kernel, caused by incorrect usage of strict_strtoul function call within set_enabled and set_disabled functions. This can be triggered by simple running the userspace client for asus_old (e.g., 'asusoled -e' or 'asusoled -d'). Signed-off-by: Eugeni Dodonov Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/asus_oled/asus_oled.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index f4c26572c7d..43c57b7688a 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c @@ -194,9 +194,11 @@ static ssize_t set_enabled(struct device *dev, struct device_attribute *attr, { struct usb_interface *intf = to_usb_interface(dev); struct asus_oled_dev *odev = usb_get_intfdata(intf); - int temp = strict_strtoul(buf, 10, NULL); + unsigned long value; + if (strict_strtoul(buf, 10, &value)) + return -EINVAL; - enable_oled(odev, temp); + enable_oled(odev, value); return count; } @@ -207,10 +209,12 @@ static ssize_t class_set_enabled(struct device *device, { struct asus_oled_dev *odev = (struct asus_oled_dev *) dev_get_drvdata(device); + unsigned long value; - int temp = strict_strtoul(buf, 10, NULL); + if (strict_strtoul(buf, 10, &value)) + return -EINVAL; - enable_oled(odev, temp); + enable_oled(odev, value); return count; } -- cgit v1.2.3-70-g09d2 From d31a2ff03f31cbecb92bdc5b1ab9d62fb70971d7 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 6 Jan 2010 14:01:26 +0000 Subject: Staging: et131x: Fix 2.6.33rc1 regression in et131x et131x: Fix 12bit wrapping From: Alan Cox The 12bit wrap logic conversion is wrong and this shows up for some memory sizes and layouts of card. Patch it up for now, once the kernel view of status is cleaned up it'll become two variables and a lot saner. Signed-off-by: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et1310_address_map.h | 18 +++++++++++++----- drivers/staging/et131x/et1310_rx.c | 6 +++--- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et1310_address_map.h b/drivers/staging/et131x/et1310_address_map.h index 6da843cc343..e715e4dcb52 100644 --- a/drivers/staging/et131x/et1310_address_map.h +++ b/drivers/staging/et131x/et1310_address_map.h @@ -203,11 +203,14 @@ typedef struct _GLOBAL_t { /* Location: */ * 9-0: pr ndes */ -#define ET_DMA10_MASK 0x3FF /* 10 bit mask for DMA10W types */ -#define ET_DMA10_WRAP 0x400 -#define ET_DMA4_MASK 0x00F /* 4 bit mask for DMA4W types */ -#define ET_DMA4_WRAP 0x010 - +#define ET_DMA12_MASK 0x0FFF /* 12 bit mask for DMA12W types */ +#define ET_DMA12_WRAP 0x1000 +#define ET_DMA10_MASK 0x03FF /* 10 bit mask for DMA10W types */ +#define ET_DMA10_WRAP 0x0400 +#define ET_DMA4_MASK 0x000F /* 4 bit mask for DMA4W types */ +#define ET_DMA4_WRAP 0x0010 + +#define INDEX12(x) ((x) & ET_DMA12_MASK) #define INDEX10(x) ((x) & ET_DMA10_MASK) #define INDEX4(x) ((x) & ET_DMA4_MASK) @@ -216,6 +219,11 @@ extern inline void add_10bit(u32 *v, int n) *v = INDEX10(*v + n) | (*v & ET_DMA10_WRAP); } +extern inline void add_12bit(u32 *v, int n) +{ + *v = INDEX12(*v + n) | (*v & ET_DMA12_WRAP); +} + /* * 10bit DMA with wrap * txdma tx queue write address reg in txdma address map at 0x1010 diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c index 3ddc9b12b8d..81c1a7478ad 100644 --- a/drivers/staging/et131x/et1310_rx.c +++ b/drivers/staging/et131x/et1310_rx.c @@ -831,10 +831,10 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev) /* Indicate that we have used this PSR entry. */ /* FIXME wrap 12 */ - rx_local->local_psr_full = (rx_local->local_psr_full + 1) & 0xFFF; - if (rx_local->local_psr_full > rx_local->PsrNumEntries - 1) { + add_12bit(&rx_local->local_psr_full, 1); + if ((rx_local->local_psr_full & 0xFFF) > rx_local->PsrNumEntries - 1) { /* Clear psr full and toggle the wrap bit */ - rx_local->local_psr_full &= 0xFFF; + rx_local->local_psr_full &= ~0xFFF; rx_local->local_psr_full ^= 0x1000; } -- cgit v1.2.3-70-g09d2 From 7692fd4d441afac728cb83fdd33349d5ba07406c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 8 Jan 2010 09:06:40 -0800 Subject: Staging: hv: fix smp problems in the hyperv core code This fixes a number of SMP problems that were in the hyperv core code. Patch originally written by K. Y. Srinivasan but forward ported to the latest in-kernel code and tweaked slightly by me. Novell, Inc. hereby disclaims all copyright in any derivative work copyright associated with this patch. Signed-off-by: K. Y. Srinivasan Cc: Hank Janssen Cc: Haiyang Zhang . Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/Hv.c | 50 +++++++++++++++++++++++----------------------- drivers/staging/hv/Hv.h | 6 +++--- drivers/staging/hv/Vmbus.c | 12 ++++++----- 3 files changed, 35 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c index c5b6613f2f2..c2809f2a2ce 100644 --- a/drivers/staging/hv/Hv.c +++ b/drivers/staging/hv/Hv.c @@ -386,7 +386,7 @@ u16 HvSignalEvent(void) * retrieve the initialized message and event pages. Otherwise, we create and * initialize the message and event pages. */ -int HvSynicInit(u32 irqVector) +void HvSynicInit(void *irqarg) { u64 version; union hv_synic_simp simp; @@ -394,13 +394,14 @@ int HvSynicInit(u32 irqVector) union hv_synic_sint sharedSint; union hv_synic_scontrol sctrl; u64 guestID; - int ret = 0; + u32 irqVector = *((u32 *)(irqarg)); + int cpu = smp_processor_id(); DPRINT_ENTER(VMBUS); if (!gHvContext.HypercallPage) { DPRINT_EXIT(VMBUS); - return ret; + return; } /* Check the version */ @@ -425,27 +426,27 @@ int HvSynicInit(u32 irqVector) */ rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID); if (guestID == HV_LINUX_GUEST_ID) { - gHvContext.synICMessagePage[0] = + gHvContext.synICMessagePage[cpu] = phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT); - gHvContext.synICEventPage[0] = + gHvContext.synICEventPage[cpu] = phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT); } else { DPRINT_ERR(VMBUS, "unknown guest id!!"); goto Cleanup; } DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p", - gHvContext.synICMessagePage[0], - gHvContext.synICEventPage[0]); + gHvContext.synICMessagePage[cpu], + gHvContext.synICEventPage[cpu]); } else { - gHvContext.synICMessagePage[0] = osd_PageAlloc(1); - if (gHvContext.synICMessagePage[0] == NULL) { + gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); + if (gHvContext.synICMessagePage[cpu] == NULL) { DPRINT_ERR(VMBUS, "unable to allocate SYNIC message page!!"); goto Cleanup; } - gHvContext.synICEventPage[0] = osd_PageAlloc(1); - if (gHvContext.synICEventPage[0] == NULL) { + gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); + if (gHvContext.synICEventPage[cpu] == NULL) { DPRINT_ERR(VMBUS, "unable to allocate SYNIC event page!!"); goto Cleanup; @@ -454,7 +455,7 @@ int HvSynicInit(u32 irqVector) /* Setup the Synic's message page */ rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64); simp.SimpEnabled = 1; - simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[0]) + simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu]) >> PAGE_SHIFT; DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", @@ -465,7 +466,7 @@ int HvSynicInit(u32 irqVector) /* Setup the Synic's event page */ rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); siefp.SiefpEnabled = 1; - siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[0]) + siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu]) >> PAGE_SHIFT; DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", @@ -501,32 +502,30 @@ int HvSynicInit(u32 irqVector) DPRINT_EXIT(VMBUS); - return ret; + return; Cleanup: - ret = -1; - if (gHvContext.GuestId == HV_LINUX_GUEST_ID) { - if (gHvContext.synICEventPage[0]) - osd_PageFree(gHvContext.synICEventPage[0], 1); + if (gHvContext.synICEventPage[cpu]) + osd_PageFree(gHvContext.synICEventPage[cpu], 1); - if (gHvContext.synICMessagePage[0]) - osd_PageFree(gHvContext.synICMessagePage[0], 1); + if (gHvContext.synICMessagePage[cpu]) + osd_PageFree(gHvContext.synICMessagePage[cpu], 1); } DPRINT_EXIT(VMBUS); - - return ret; + return; } /** * HvSynicCleanup - Cleanup routine for HvSynicInit(). */ -void HvSynicCleanup(void) +void HvSynicCleanup(void *arg) { union hv_synic_sint sharedSint; union hv_synic_simp simp; union hv_synic_siefp siefp; + int cpu = smp_processor_id(); DPRINT_ENTER(VMBUS); @@ -539,6 +538,7 @@ void HvSynicCleanup(void) sharedSint.Masked = 1; + /* Need to correctly cleanup in the case of SMP!!! */ /* Disable the interrupt */ wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64); @@ -560,8 +560,8 @@ void HvSynicCleanup(void) wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); - osd_PageFree(gHvContext.synICMessagePage[0], 1); - osd_PageFree(gHvContext.synICEventPage[0], 1); + osd_PageFree(gHvContext.synICMessagePage[cpu], 1); + osd_PageFree(gHvContext.synICEventPage[cpu], 1); } DPRINT_EXIT(VMBUS); diff --git a/drivers/staging/hv/Hv.h b/drivers/staging/hv/Hv.h index 5379e4bfc56..fce4b5cdac3 100644 --- a/drivers/staging/hv/Hv.h +++ b/drivers/staging/hv/Hv.h @@ -93,7 +93,7 @@ static const struct hv_guid VMBUS_SERVICE_ID = { }, }; -#define MAX_NUM_CPUS 1 +#define MAX_NUM_CPUS 32 struct hv_input_signal_event_buffer { @@ -137,8 +137,8 @@ extern u16 HvPostMessage(union hv_connection_id connectionId, extern u16 HvSignalEvent(void); -extern int HvSynicInit(u32 irqVector); +extern void HvSynicInit(void *irqarg); -extern void HvSynicCleanup(void); +extern void HvSynicCleanup(void *arg); #endif /* __HV_H__ */ diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c index a4dd06f6d45..35a023e9f9d 100644 --- a/drivers/staging/hv/Vmbus.c +++ b/drivers/staging/hv/Vmbus.c @@ -129,7 +129,7 @@ static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo) /* strcpy(dev->name, "vmbus"); */ /* SynIC setup... */ - ret = HvSynicInit(*irqvector); + on_each_cpu(HvSynicInit, (void *)irqvector, 1); /* Connect to VMBus in the root partition */ ret = VmbusConnect(); @@ -150,7 +150,7 @@ static int VmbusOnDeviceRemove(struct hv_device *dev) DPRINT_ENTER(VMBUS); VmbusChannelReleaseUnattachedChannels(); VmbusDisconnect(); - HvSynicCleanup(); + on_each_cpu(HvSynicCleanup, NULL, 1); DPRINT_EXIT(VMBUS); return ret; @@ -173,7 +173,8 @@ static void VmbusOnCleanup(struct hv_driver *drv) */ static void VmbusOnMsgDPC(struct hv_driver *drv) { - void *page_addr = gHvContext.synICMessagePage[0]; + int cpu = smp_processor_id(); + void *page_addr = gHvContext.synICMessagePage[cpu]; struct hv_message *msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; struct hv_message *copied; @@ -230,11 +231,12 @@ static void VmbusOnEventDPC(struct hv_driver *drv) static int VmbusOnISR(struct hv_driver *drv) { int ret = 0; + int cpu = smp_processor_id(); void *page_addr; struct hv_message *msg; union hv_synic_event_flags *event; - page_addr = gHvContext.synICMessagePage[0]; + page_addr = gHvContext.synICMessagePage[cpu]; msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; DPRINT_ENTER(VMBUS); @@ -248,7 +250,7 @@ static int VmbusOnISR(struct hv_driver *drv) } /* TODO: Check if there are events to be process */ - page_addr = gHvContext.synICEventPage[0]; + page_addr = gHvContext.synICEventPage[cpu]; event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; /* Since we are a child, we only need to check bit 0 */ -- cgit v1.2.3-70-g09d2 From 25719e6b4631959c9ecb1db6967537a124c4a7fa Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Tue, 5 Jan 2010 14:30:31 +0100 Subject: USB: serial: fix USB serial fix kfifo_len locking This patch fix a possible race bug in drivers/usb/serial/generic with the new kfifo API. Please apply it to the 2.6.33-rc* tree. Signed-off-by: Stefani Seibold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index f1ea3a33b6e..5ce033ab9b9 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -386,12 +386,12 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) dbg("%s - port %d", __func__, port->number); - if (serial->type->max_in_flight_urbs) { - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->lock, flags); + if (serial->type->max_in_flight_urbs) chars = port->tx_bytes_flight; - spin_unlock_irqrestore(&port->lock, flags); - } else if (serial->num_bulk_out) + else if (serial->num_bulk_out) chars = kfifo_len(&port->write_fifo); + spin_unlock_irqrestore(&port->lock, flags); dbg("%s - returns %d", __func__, chars); return chars; -- cgit v1.2.3-70-g09d2 From 2591530204a76fecc843529ade56afe865dd2657 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 6 Jan 2010 15:48:42 -0800 Subject: usb: serial: fix memory leak in generic driver Fix a regression introduced by commit 715b1dc01fe44537e8fce9566e4bb48d6821d84b ("USB: usb_debug, usb_generic_serial: implement multi urb write"). URB transfer buffer was never freed when using multi-urb writes. Currently the only driver enabling multi-urb writes is usb_debug. Signed-off-by: Johan Hovold Cc: Greg KH Acked-by: Jason Wessel Cc: stable Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 5ce033ab9b9..83443d6306d 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -489,6 +489,8 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) dbg("%s - port %d", __func__, port->number); if (port->serial->type->max_in_flight_urbs) { + kfree(urb->transfer_buffer); + spin_lock_irqsave(&port->lock, flags); --port->urbs_in_flight; port->tx_bytes_flight -= urb->transfer_buffer_length; -- cgit v1.2.3-70-g09d2 From a91b593edd4b3e8aa91f671b763b27b8119eb49d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 22 Dec 2009 23:16:32 -0500 Subject: USB: fix bitmask merge error This patch adds a mask bit which was mistakenly omitted from the as1311 patch (usb-storage: add BAD_SENSE flag). Signed-off-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 5a53d4f0dd1..e9f995486ec 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -434,7 +434,8 @@ static void adjust_quirks(struct us_data *us) u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor); u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct); unsigned f = 0; - unsigned int mask = (US_FL_SANE_SENSE | US_FL_FIX_CAPACITY | + unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE | + US_FL_FIX_CAPACITY | US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE | US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 | US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE | -- cgit v1.2.3-70-g09d2 From acbe2febe71abb2360b008e9ab3ee5c44169f78c Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 12 Jan 2010 12:32:50 +0100 Subject: USB: Don't use GFP_KERNEL while we cannot reset a storage device Memory allocations with GFP_KERNEL can cause IO to a storage device which can fail resulting in a need to reset the device. Therefore GFP_KERNEL cannot be safely used between usb_lock_device() and usb_unlock_device(). Replace by GFP_NOIO. Signed-off-by: Oliver Neukum Cc: stable Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 2 +- drivers/usb/core/message.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 96f11715cd2..355dffcc23b 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -494,7 +494,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, return 0; /* allocate 2^1 pages = 8K (on i386); * should be more than enough for one device */ - pages_start = (char *)__get_free_pages(GFP_KERNEL, 1); + pages_start = (char *)__get_free_pages(GFP_NOIO, 1); if (!pages_start) return -ENOMEM; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 1b994846e8e..9bc95fec793 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -906,11 +906,11 @@ char *usb_cache_string(struct usb_device *udev, int index) if (index <= 0) return NULL; - buf = kmalloc(MAX_USB_STRING_SIZE, GFP_KERNEL); + buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO); if (buf) { len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE); if (len > 0) { - smallbuf = kmalloc(++len, GFP_KERNEL); + smallbuf = kmalloc(++len, GFP_NOIO); if (!smallbuf) return buf; memcpy(smallbuf, buf, len); @@ -1731,7 +1731,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (cp) { nintf = cp->desc.bNumInterfaces; new_interfaces = kmalloc(nintf * sizeof(*new_interfaces), - GFP_KERNEL); + GFP_NOIO); if (!new_interfaces) { dev_err(&dev->dev, "Out of memory\n"); return -ENOMEM; @@ -1740,7 +1740,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) for (; n < nintf; ++n) { new_interfaces[n] = kzalloc( sizeof(struct usb_interface), - GFP_KERNEL); + GFP_NOIO); if (!new_interfaces[n]) { dev_err(&dev->dev, "Out of memory\n"); ret = -ENOMEM; -- cgit v1.2.3-70-g09d2 From 1b9a38bfa6e664ff02511314f5586d711c83cc91 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 8 Jan 2010 11:17:55 -0500 Subject: USB: EHCI: fix handling of unusual interrupt intervals This patch (as1320) fixes two problems related to interrupt-URB scheduling in ehci-hcd. URBs with an interval of 2 or 4 microframes aren't handled. For the time being, the patch reduces to interval to 1 uframe. URBs are constrained to have an interval no larger than 1024 frames by usb_submit_urb(). But some EHCI controllers allow use of a schedule as short as 256 frames; for these controllers we may have to decrease the interval to the actual schedule length. The second problem isn't very significant since few devices expose interrupt endpoints with an interval larger than 256 frames. But the first problem is critical; it will prevent the kernel from working with devices having interrupt intervals of 2 or 4 uframes. Signed-off-by: Alan Stern Cc: stable Tested-by: Glynn Farrow Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index a427d3b0063..89521775c56 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -849,9 +849,10 @@ qh_make ( * But interval 1 scheduling is simpler, and * includes high bandwidth. */ - dbg ("intr period %d uframes, NYET!", - urb->interval); - goto done; + urb->interval = 1; + } else if (qh->period > ehci->periodic_size) { + qh->period = ehci->periodic_size; + urb->interval = qh->period << 3; } } else { int think_time; @@ -874,6 +875,10 @@ qh_make ( usb_calc_bus_time (urb->dev->speed, is_input, 0, max_packet (maxp))); qh->period = urb->interval; + if (qh->period > ehci->periodic_size) { + qh->period = ehci->periodic_size; + urb->interval = qh->period; + } } } -- cgit v1.2.3-70-g09d2 From cec3a53c7fe794237b582e8e77fc0e48465e65ee Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 8 Jan 2010 11:18:20 -0500 Subject: USB: EHCI & UHCI: fix race between root-hub suspend and port resume This patch (as1321) fixes a problem with EHCI and UHCI root-hub suspends: If the suspend occurs while a port is trying to resume, the resume doesn't finish and simply gets lost. When remote wakeup is enabled, this is undesirable behavior. The patch checks first to see if any port resumes are in progress, and if they are then it fails the root-hub suspend with -EBUSY. Signed-off-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 20 +++++++++++++++++++- drivers/usb/host/uhci-hcd.c | 15 ++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 2c6571c05f3..c75d9270c75 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -120,9 +120,26 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) del_timer_sync(&ehci->watchdog); del_timer_sync(&ehci->iaa_watchdog); - port = HCS_N_PORTS (ehci->hcs_params); spin_lock_irq (&ehci->lock); + /* Once the controller is stopped, port resumes that are already + * in progress won't complete. Hence if remote wakeup is enabled + * for the root hub and any ports are in the middle of a resume or + * remote wakeup, we must fail the suspend. + */ + if (hcd->self.root_hub->do_remote_wakeup) { + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { + if (ehci->reset_done[port] != 0) { + spin_unlock_irq(&ehci->lock); + ehci_dbg(ehci, "suspend failed because " + "port %d is resuming\n", + port + 1); + return -EBUSY; + } + } + } + /* stop schedules, clean any completed work */ if (HC_IS_RUNNING(hcd->state)) { ehci_quiesce (ehci); @@ -138,6 +155,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) */ ehci->bus_suspended = 0; ehci->owned_ports = 0; + port = HCS_N_PORTS(ehci->hcs_params); while (port--) { u32 __iomem *reg = &ehci->regs->port_status [port]; u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 5cd0e48f67f..99cd00fd351 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -749,7 +749,20 @@ static int uhci_rh_suspend(struct usb_hcd *hcd) spin_lock_irq(&uhci->lock); if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) rc = -ESHUTDOWN; - else if (!uhci->dead) + else if (uhci->dead) + ; /* Dead controllers tell no tales */ + + /* Once the controller is stopped, port resumes that are already + * in progress won't complete. Hence if remote wakeup is enabled + * for the root hub and any ports are in the middle of a resume or + * remote wakeup, we must fail the suspend. + */ + else if (hcd->self.root_hub->do_remote_wakeup && + uhci->resuming_ports) { + dev_dbg(uhci_dev(uhci), "suspend failed because a port " + "is resuming\n"); + rc = -EBUSY; + } else suspend_rh(uhci, UHCI_RH_SUSPENDED); spin_unlock_irq(&uhci->lock); return rc; -- cgit v1.2.3-70-g09d2 From 49d0f078f494b9d81e820a13dd8093a9bfb0b6b1 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 8 Jan 2010 11:18:38 -0500 Subject: USB: add missing delay during remote wakeup This patch (as1330) fixes a bug in khbud's handling of remote wakeups. When a device sends a remote-wakeup request, the parent hub (or the host controller driver, for directly attached devices) begins the resume sequence and notifies khubd when the sequence finishes. At this point the port's SUSPEND feature is automatically turned off. However the device needs an additional 10-ms resume-recovery time (TRSMRCY in the USB spec). Khubd does not wait for this delay if the SUSPEND feature is off, and as a result some devices fail to behave properly following a remote wakeup. This patch adds the missing delay to the remote-wakeup path. It also extends the resume-signalling delay used by ehci-hcd and uhci-hcd from 20 ms (the value in the spec) to 25 ms (the value we use for non-remote-wakeup resumes). The extra time appears to help some devices. Signed-off-by: Alan Stern Cc: stable Cc: Rickard Bellini Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 3 +++ drivers/usb/host/ehci-hcd.c | 5 +++-- drivers/usb/host/uhci-hub.c | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0cec6caf6e9..b9f5fcd713e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3347,6 +3347,9 @@ static void hub_events(void) USB_PORT_FEAT_C_SUSPEND); udev = hdev->children[i-1]; if (udev) { + /* TRSMRCY = 10 msec */ + msleep(10); + usb_lock_device(udev); ret = remote_wakeup(hdev-> children[i-1]); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 5859522d6ed..1ec3857f22e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -787,9 +787,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* start 20 msec resume signaling from this port, * and make khubd collect PORT_STAT_C_SUSPEND to - * stop that signaling. + * stop that signaling. Use 5 ms extra for safety, + * like usb_port_resume() does. */ - ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); + ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); mod_timer(&hcd->rh_timer, ehci->reset_done[i]); } diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 885b585360b..8270055848c 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -167,7 +167,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci) /* Port received a wakeup request */ set_bit(port, &uhci->resuming_ports); uhci->ports_timeout = jiffies + - msecs_to_jiffies(20); + msecs_to_jiffies(25); /* Make sure we see the port again * after the resuming period is over. */ -- cgit v1.2.3-70-g09d2 From b132b04e193908a94d95065d0628f8fb0159cc55 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 14 Jan 2010 10:33:19 -0800 Subject: USB: add speed values for USB 3.0 and wireless controllers These controllers say "unknown" for their speed in sysfs, which obviously isn't correct. Reported-by: Kurt Garloff Cc: Sarah Sharp Cc: David Vrabel Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 485edf937f2..5f3908f6e2d 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -115,6 +115,12 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf) case USB_SPEED_HIGH: speed = "480"; break; + case USB_SPEED_VARIABLE: + speed = "480"; + break; + case USB_SPEED_SUPER: + speed = "5000"; + break; default: speed = "unknown"; } -- cgit v1.2.3-70-g09d2 From 04a723ea9c53ba608b0411aa36948bb57c51a08e Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 6 Jan 2010 10:16:51 -0800 Subject: USB: Fix duplicate sysfs problem after device reset. Borislav Petkov reports issues with duplicate sysfs endpoint files after a resume from a hibernate. It turns out that the code to support alternate settings under xHCI has issues when a device with a non-default alternate setting is reset during the hibernate: [ 427.681810] Restarting tasks ... [ 427.681995] hub 1-0:1.0: state 7 ports 6 chg 0004 evt 0000 [ 427.682019] usb usb3: usb resume [ 427.682030] ohci_hcd 0000:00:12.0: wakeup root hub [ 427.682191] hub 1-0:1.0: port 2, status 0501, change 0000, 480 Mb/s [ 427.682205] usb 1-2: usb wakeup-resume [ 427.682226] usb 1-2: finish reset-resume [ 427.682886] done. [ 427.734658] ehci_hcd 0000:00:12.2: port 2 high speed [ 427.734663] ehci_hcd 0000:00:12.2: GetStatus port 2 status 001005 POWER sig=se0 PE CONNECT [ 427.746682] hub 3-0:1.0: hub_reset_resume [ 427.746693] hub 3-0:1.0: trying to enable port power on non-switchable hub [ 427.786715] usb 1-2: reset high speed USB device using ehci_hcd and address 2 [ 427.839653] ehci_hcd 0000:00:12.2: port 2 high speed [ 427.839666] ehci_hcd 0000:00:12.2: GetStatus port 2 status 001005 POWER sig=se0 PE CONNECT [ 427.847717] ohci_hcd 0000:00:12.0: GetStatus roothub.portstatus [1] = 0x00010100 CSC PPS [ 427.915497] hub 1-2:1.0: remove_intf_ep_devs: if: ffff88022f9e8800 ->ep_devs_created: 1 [ 427.915774] hub 1-2:1.0: remove_intf_ep_devs: bNumEndpoints: 1 [ 427.915934] hub 1-2:1.0: if: ffff88022f9e8800: endpoint devs removed. [ 427.916158] hub 1-2:1.0: create_intf_ep_devs: if: ffff88022f9e8800 ->ep_devs_created: 0, ->unregistering: 0 [ 427.916434] hub 1-2:1.0: create_intf_ep_devs: bNumEndpoints: 1 [ 427.916609] ep_81: create, parent hub [ 427.916632] ------------[ cut here ]------------ [ 427.916644] WARNING: at fs/sysfs/dir.c:477 sysfs_add_one+0x82/0x96() [ 427.916649] Hardware name: System Product Name [ 427.916653] sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:12.2/usb1/1-2/1-2:1.0/ep_81' [ 427.916658] Modules linked in: binfmt_misc kvm_amd kvm powernow_k8 cpufreq_ondemand cpufreq_powersave cpufreq_userspace freq_table cpufreq_conservative ipv6 vfat fat +8250_pnp 8250 pcspkr ohci_hcd serial_core k10temp edac_core [ 427.916694] Pid: 278, comm: khubd Not tainted 2.6.33-rc2-00187-g08d869a-dirty #13 [ 427.916699] Call Trace: The problem is caused by a mismatch between the USB core's view of the device state and the USB device and xHCI host's view of the device state. After the device reset and re-configuration, the device and the xHCI host think they are using alternate setting 0 of all interfaces. However, the USB core keeps track of the old state, which may include non-zero alternate settings. It uses intf->cur_altsetting to keep the endpoint sysfs files for the old state across the reset. The bandwidth allocation functions need to know what the xHCI host thinks the current alternate settings are, so original patch set intf->cur_altsetting to the alternate setting 0. This caused duplicate endpoint files to be created. The solution is to not set intf->cur_altsetting before calling usb_set_interface() in usb_reset_and_verify_device(). Instead, we add a new flag to struct usb_interface to tell usb_hcd_alloc_bandwidth() to use alternate setting 0 as the currently installed alternate setting. Signed-off-by: Sarah Sharp Tested-by: Borislav Petkov Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 18 ++++++++++++++++++ drivers/usb/core/hub.c | 15 +++++---------- include/linux/usb.h | 1 + 3 files changed, 24 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0495fa65122..80995ef0868 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1684,6 +1684,24 @@ int usb_hcd_alloc_bandwidth(struct usb_device *udev, } } if (cur_alt && new_alt) { + struct usb_interface *iface = usb_ifnum_to_if(udev, + cur_alt->desc.bInterfaceNumber); + + if (iface->resetting_device) { + /* + * The USB core just reset the device, so the xHCI host + * and the device will think alt setting 0 is installed. + * However, the USB core will pass in the alternate + * setting installed before the reset as cur_alt. Dig + * out the alternate setting 0 structure, or the first + * alternate setting if a broken device doesn't have alt + * setting 0. + */ + cur_alt = usb_altnum_to_altsetting(iface, 0); + if (!cur_alt) + cur_alt = &iface->altsetting[0]; + } + /* Drop all the endpoints in the current alt setting */ for (i = 0; i < cur_alt->desc.bNumEndpoints; i++) { ret = hcd->driver->drop_endpoint(hcd, udev, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b9f5fcd713e..35cc8b9ba1f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3695,19 +3695,14 @@ static int usb_reset_and_verify_device(struct usb_device *udev) usb_enable_interface(udev, intf, true); ret = 0; } else { - /* We've just reset the device, so it will think alt - * setting 0 is installed. For usb_set_interface() to - * work properly, we need to set the current alternate - * interface setting to 0 (or the first alt setting, if - * the device doesn't have alt setting 0). + /* Let the bandwidth allocation function know that this + * device has been reset, and it will have to use + * alternate setting 0 as the current alternate setting. */ - intf->cur_altsetting = - usb_find_alt_setting(config, i, 0); - if (!intf->cur_altsetting) - intf->cur_altsetting = - &config->intf_cache[i]->altsetting[0]; + intf->resetting_device = 1; ret = usb_set_interface(udev, desc->bInterfaceNumber, desc->bAlternateSetting); + intf->resetting_device = 0; } if (ret < 0) { dev_err(&udev->dev, "failed to restore interface %d " diff --git a/include/linux/usb.h b/include/linux/usb.h index e101a2d04d7..d7ace1b80f0 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -192,6 +192,7 @@ struct usb_interface { unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */ unsigned needs_binding:1; /* needs delayed unbind/rebind */ unsigned reset_running:1; + unsigned resetting_device:1; /* true: bandwidth alloc after reset */ struct device dev; /* interface specific device info */ struct device *usb_dev; -- cgit v1.2.3-70-g09d2 From ae35fe9e8abe828b25053cd3efdc6953fbb710e3 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Thu, 7 Jan 2010 04:17:32 +0300 Subject: USB: FHCI: avoid NULL pointer dereference Assign fhci only if usb is not NULL. Signed-off-by: Alexander Beregalov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fhci-hcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 0951818ef93..78e7c3cfcb7 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -242,9 +242,10 @@ err: static void fhci_usb_free(void *lld) { struct fhci_usb *usb = lld; - struct fhci_hcd *fhci = usb->fhci; + struct fhci_hcd *fhci; if (usb) { + fhci = usb->fhci; fhci_config_transceiver(fhci, FHCI_PORT_POWER_OFF); fhci_ep0_free(usb); kfree(usb->actual_frame); -- cgit v1.2.3-70-g09d2 From c0d74142531c7ec23bb29885aec8f924ee4c1a46 Mon Sep 17 00:00:00 2001 From: Colin Tuckley Date: Thu, 7 Jan 2010 11:22:47 +0000 Subject: USB: Fix level of isp1760 Reloading ptd error message This error message is not actually an error, it's an information message. It is triggered when a transfer which ended in a NAQ is retried successfully by the hardware. Signed-off-by: Colin Tuckley Cc: Sebastian Andrzej Siewior Cc: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-hcd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 9600a58299d..27b8f7cb447 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -1039,12 +1039,12 @@ static void do_atl_int(struct usb_hcd *usb_hcd) if (!nakcount && (dw3 & DW3_QTD_ACTIVE)) { u32 buffstatus; - /* XXX + /* * NAKs are handled in HW by the chip. Usually if the * device is not able to send data fast enough. - * This did not trigger for a long time now. + * This happens mostly on slower hardware. */ - printk(KERN_ERR "Reloading ptd %p/%p... qh %p readed: " + printk(KERN_NOTICE "Reloading ptd %p/%p... qh %p read: " "%d of %zu done: %08x cur: %08x\n", qtd, urb, qh, PTD_XFERRED_LENGTH(dw3), qtd->length, done_map, -- cgit v1.2.3-70-g09d2 From 10d2cdb6102669279bee2d9a00a22431b74583d5 Mon Sep 17 00:00:00 2001 From: Ryan May Date: Wed, 6 Jan 2010 10:09:25 -0600 Subject: USB: fix usbstorage for 2770:915d delivers no FAT Resolves kernel.org bug 14914. Remove entry for 2770:915d (usb digital camera with mass storage support) from unusual_devs.h. The fix triggered by the entry causes the file system on the camera to be completely inaccessible (no partition table, the device is not mountable). The patch works, but let me clarify a few things about it. All the patch does is remove the entry for this device from the drivers/usb/storage/unusual_devs.h, which is supposed to help with a problem with the device's reported size (I think). I'm pretty sure it was originally added for a reason, so I'm not sure removing it won't cause other problems to reappear. Also, I should note that this unusual_devs.h entry was present (and activating workarounds) in 2.6.29, but in that version everything works fine. Starting with 2.6.30, things no longer work. Signed-off-by: Ryan May Cc: Rohan Hart Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 64a0a2c27e1..c932f905318 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1807,13 +1807,6 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_GO_SLOW ), -/* Reported by Rohan Hart */ -UNUSUAL_DEV( 0x2770, 0x915d, 0x0010, 0x0010, - "INTOVA", - "Pixtreme", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY ), - /* Reported by Frederic Marchal * Mio Moov 330 */ -- cgit v1.2.3-70-g09d2 From 96b85179b464cc80d85b5c602af119d1dd6d50bb Mon Sep 17 00:00:00 2001 From: Lothar Wassmann Date: Fri, 15 Jan 2010 08:04:55 -0500 Subject: USB: isp1362: better 64bit printf warning fixes Some hosts that treat the return value of sizeof differently from unsigned long might still hit warnings. So use %zu for sizeof() values. This is a better version of the previous commit b0a9cf297e58721933. Signed-off-by: Lothar Wassmann Signed-off-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 73352f3739b..8d3104441f1 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2270,10 +2270,10 @@ static int isp1362_mem_config(struct usb_hcd *hcd) dev_info(hcd->self.controller, "ISP1362 Memory usage:\n"); dev_info(hcd->self.controller, " ISTL: 2 * %4d: %4d @ $%04x:$%04x\n", istl_size / 2, istl_size, 0, istl_size / 2); - dev_info(hcd->self.controller, " INTL: %4d * (%3lu+8): %4d @ $%04x\n", + dev_info(hcd->self.controller, " INTL: %4d * (%3zu+8): %4d @ $%04x\n", ISP1362_INTL_BUFFERS, intl_blksize - PTD_HEADER_SIZE, intl_size, istl_size); - dev_info(hcd->self.controller, " ATL : %4d * (%3lu+8): %4d @ $%04x\n", + dev_info(hcd->self.controller, " ATL : %4d * (%3zu+8): %4d @ $%04x\n", atl_buffers, atl_blksize - PTD_HEADER_SIZE, atl_size, istl_size + intl_size); dev_info(hcd->self.controller, " USED/FREE: %4d %4d\n", total, -- cgit v1.2.3-70-g09d2 From 0a2fea2e0dea9df8ead1cb45e4b9cd68e1b1d29b Mon Sep 17 00:00:00 2001 From: Lothar Wassmann Date: Fri, 15 Jan 2010 14:42:02 -0500 Subject: USB: isp1362: fix build failure on ARM systems via irq_flags cleanup There was some left over #ifdef ARM logic that is outdated but no one really noticed. So instead of relying on this tricky logic, properly load and utilize the platform irq_flags resources. Reported-by: Ben Hutchings Signed-off-by: Lothar Wassmann Signed-off-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 8d3104441f1..42971657fde 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2697,6 +2697,8 @@ static int __init isp1362_probe(struct platform_device *pdev) void __iomem *data_reg; int irq; int retval = 0; + struct resource *irq_res; + unsigned int irq_flags = 0; /* basic sanity checks first. board-specific init logic should * have initialized this the three resources and probably board @@ -2710,11 +2712,12 @@ static int __init isp1362_probe(struct platform_device *pdev) data = platform_get_resource(pdev, IORESOURCE_MEM, 0); addr = platform_get_resource(pdev, IORESOURCE_MEM, 1); - irq = platform_get_irq(pdev, 0); - if (!addr || !data || irq < 0) { + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!addr || !data || !irq_res) { retval = -ENODEV; goto err1; } + irq = irq_res->start; #ifdef CONFIG_USB_HCD_DMA if (pdev->dev.dma_mask) { @@ -2781,12 +2784,16 @@ static int __init isp1362_probe(struct platform_device *pdev) } #endif -#ifdef CONFIG_ARM - if (isp1362_hcd->board) - set_irq_type(irq, isp1362_hcd->board->int_act_high ? IRQT_RISING : IRQT_FALLING); -#endif + if (irq_res->flags & IORESOURCE_IRQ_HIGHEDGE) + irq_flags |= IRQF_TRIGGER_RISING; + if (irq_res->flags & IORESOURCE_IRQ_LOWEDGE) + irq_flags |= IRQF_TRIGGER_FALLING; + if (irq_res->flags & IORESOURCE_IRQ_HIGHLEVEL) + irq_flags |= IRQF_TRIGGER_HIGH; + if (irq_res->flags & IORESOURCE_IRQ_LOWLEVEL) + irq_flags |= IRQF_TRIGGER_LOW; - retval = usb_add_hcd(hcd, irq, IRQF_TRIGGER_LOW | IRQF_DISABLED | IRQF_SHARED); + retval = usb_add_hcd(hcd, irq, irq_flags | IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err6; pr_info("%s, irq %d\n", hcd->product_desc, irq); -- cgit v1.2.3-70-g09d2 From c1fa347f20f17f14a4a1575727fa24340e8a9117 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 19 Jan 2010 14:21:45 +0000 Subject: e1000/e1000e/igb/igbvf/ixgb/ixgbe: Fix tests of unsigned in *_tx_map() The variable count and i are unsigned so the (<|>=)0 tests do not work. Signed-off-by: Roel Kluin Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 10 +++++----- drivers/net/e1000e/netdev.c | 10 +++++----- drivers/net/igbvf/netdev.c | 10 +++++----- drivers/net/ixgb/ixgb_main.c | 10 +++++----- drivers/net/ixgbe/ixgbe_main.c | 10 +++++----- 5 files changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7e855f9bbd9..b3f67b41627 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2802,13 +2802,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter, dma_error: dev_err(&pdev->dev, "TX DMA map failed\n"); buffer_info->dma = 0; - count--; - - while (count >= 0) { + if (count) count--; - i--; - if (i < 0) + + while (count--) { + if (i==0) i += tx_ring->count; + i--; buffer_info = &tx_ring->buffer_info[i]; e1000_unmap_and_free_tx_resource(adapter, buffer_info); } diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index c45965a256b..f91f247ed6a 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3962,13 +3962,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter, dma_error: dev_err(&pdev->dev, "TX DMA map failed\n"); buffer_info->dma = 0; - count--; - - while (count >= 0) { + if (count) count--; - i--; - if (i < 0) + + while (count--) { + if (i==0) i += tx_ring->count; + i--; buffer_info = &tx_ring->buffer_info[i]; e1000_put_txbuf(adapter, buffer_info);; } diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 0dbd0320023..10e038adba0 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -2163,14 +2163,14 @@ dma_error: buffer_info->length = 0; buffer_info->next_to_watch = 0; buffer_info->mapped_as_page = false; - count--; + if (count) + count--; /* clear timestamp and dma mappings for remaining portion of packet */ - while (count >= 0) { - count--; - i--; - if (i < 0) + while (count--) { + if (i==0) i += tx_ring->count; + i--; buffer_info = &tx_ring->buffer_info[i]; igbvf_put_txbuf(adapter, buffer_info); } diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index bcd0f01d5fe..593d1a4f217 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1363,13 +1363,13 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, dma_error: dev_err(&pdev->dev, "TX DMA map failed\n"); buffer_info->dma = 0; - count--; - - while (count >= 0) { + if (count) count--; - i--; - if (i < 0) + + while (count--) { + if (i==0) i += tx_ring->count; + i--; buffer_info = &tx_ring->buffer_info[i]; ixgb_unmap_and_free_tx_resource(adapter, buffer_info); } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 9c9202f40b1..6d61add27a0 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -5167,14 +5167,14 @@ dma_error: tx_buffer_info->dma = 0; tx_buffer_info->time_stamp = 0; tx_buffer_info->next_to_watch = 0; - count--; + if (count) + count--; /* clear timestamp and dma mappings for remaining portion of packet */ - while (count >= 0) { - count--; - i--; - if (i < 0) + while (count--) { + if (i==0) i += tx_ring->count; + i--; tx_buffer_info = &tx_ring->tx_buffer_info[i]; ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info); } -- cgit v1.2.3-70-g09d2 From 40a14deaf411592b57cb0720f0e8004293ab9865 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 19 Jan 2010 14:15:38 +0000 Subject: e1000: enhance frame fragment detection Originally From: Neil Horman Modified by: Jesse Brandeburg Hey all- A security discussion was recently given: http://events.ccc.de/congress/2009/Fahrplan//events/3596.en.html And a patch that I submitted awhile back was brought up. Apparently some of their testing revealed that they were able to force a buffer fragment in e1000 in which the trailing fragment was greater than 4 bytes. As a result the fragment check I introduced failed to detect the fragement and a partial invalid frame was passed up into the network stack. I've written this patch to correct it. I'm in the process of testing it now, but it makes good logical sense to me. Effectively it maintains a per-adapter state variable which detects a non-EOP frame, and discards it and subsequent non-EOP frames leading up to _and_ _including_ the next positive-EOP frame (as it is by definition the last fragment). This should prevent any and all partial frames from entering the network stack from e1000. Signed-off-by: Jesse Brandeburg Acked-by: Neil Horman Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000.h | 2 ++ drivers/net/e1000/e1000_main.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 2a567df3ea7..e8932db7ee7 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -326,6 +326,8 @@ struct e1000_adapter { /* for ioport free */ int bars; int need_ioport; + + bool discarding; }; enum e1000_state_t { diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index b3f67b41627..a53a2017c53 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3850,13 +3850,22 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, length = le16_to_cpu(rx_desc->length); /* !EOP means multiple descriptors were used to store a single - * packet, also make sure the frame isn't just CRC only */ - if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) { + * packet, if thats the case we need to toss it. In fact, we + * to toss every packet with the EOP bit clear and the next + * frame that _does_ have the EOP bit set, as it is by + * definition only a frame fragment + */ + if (unlikely(!(status & E1000_RXD_STAT_EOP))) + adapter->discarding = true; + + if (adapter->discarding) { /* All receives must fit into a single buffer */ E1000_DBG("%s: Receive packet consumed multiple" " buffers\n", netdev->name); /* recycle */ buffer_info->skb = skb; + if (status & E1000_RXD_STAT_EOP) + adapter->discarding = false; goto next_desc; } -- cgit v1.2.3-70-g09d2 From b94b50289622e816adc9f94111cfc2679c80177c Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 19 Jan 2010 14:15:59 +0000 Subject: e1000e: enhance frame fragment detection Originally patched by Neil Horman e1000e could with a jumbo frame enabled interface, and packet split disabled, receive a packet that would overflow a single rx buffer. While in practice very hard to craft a packet that could abuse this, it is possible. this is related to CVE-2009-4538 Signed-off-by: Jesse Brandeburg CC: Neil Horman Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/e1000.h | 1 + drivers/net/e1000e/netdev.c | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index d6ee28f6ea0..d236efaf747 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -421,6 +421,7 @@ struct e1000_info { /* CRC Stripping defines */ #define FLAG2_CRC_STRIPPING (1 << 0) #define FLAG2_HAS_PHY_WAKEUP (1 << 1) +#define FLAG2_IS_DISCARDING (1 << 2) #define E1000_RX_DESC_PS(R, i) \ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index f91f247ed6a..1ea395b6c99 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -450,13 +450,23 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, length = le16_to_cpu(rx_desc->length); - /* !EOP means multiple descriptors were used to store a single - * packet, also make sure the frame isn't just CRC only */ - if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) { + /* + * !EOP means multiple descriptors were used to store a single + * packet, if that's the case we need to toss it. In fact, we + * need to toss every packet with the EOP bit clear and the + * next frame that _does_ have the EOP bit set, as it is by + * definition only a frame fragment + */ + if (unlikely(!(status & E1000_RXD_STAT_EOP))) + adapter->flags2 |= FLAG2_IS_DISCARDING; + + if (adapter->flags2 & FLAG2_IS_DISCARDING) { /* All receives must fit into a single buffer */ e_dbg("Receive packet consumed multiple buffers\n"); /* recycle */ buffer_info->skb = skb; + if (status & E1000_RXD_STAT_EOP) + adapter->flags2 &= ~FLAG2_IS_DISCARDING; goto next_desc; } @@ -745,10 +755,16 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, PCI_DMA_FROMDEVICE); buffer_info->dma = 0; - if (!(staterr & E1000_RXD_STAT_EOP)) { + /* see !EOP comment in other rx routine */ + if (!(staterr & E1000_RXD_STAT_EOP)) + adapter->flags2 |= FLAG2_IS_DISCARDING; + + if (adapter->flags2 & FLAG2_IS_DISCARDING) { e_dbg("Packet Split buffers didn't pick up the full " "packet\n"); dev_kfree_skb_irq(skb); + if (staterr & E1000_RXD_STAT_EOP) + adapter->flags2 &= ~FLAG2_IS_DISCARDING; goto next_desc; } @@ -1118,6 +1134,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; + adapter->flags2 &= ~FLAG2_IS_DISCARDING; writel(0, adapter->hw.hw_addr + rx_ring->head); writel(0, adapter->hw.hw_addr + rx_ring->tail); -- cgit v1.2.3-70-g09d2 From b81124696e6a47d5db02b2b3561d66d1392b0f2f Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Wed, 20 Jan 2010 12:41:13 -0800 Subject: wimax/i2400m: Add support for more i6x50 SKUs The Intel WiMax Wireless Link 6050 can show under more than one USB ID. Add support for all, introducing a generic flag (i2400mu->i6050) that denotes a 6x50 based device. Signed-off-by: Inaky Perez-Gonzalez --- drivers/net/wimax/i2400m/i2400m-usb.h | 2 ++ drivers/net/wimax/i2400m/usb.c | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h index 5cc0f279417..2d7c96d7e86 100644 --- a/drivers/net/wimax/i2400m/i2400m-usb.h +++ b/drivers/net/wimax/i2400m/i2400m-usb.h @@ -151,6 +151,7 @@ enum { /* Device IDs */ USB_DEVICE_ID_I6050 = 0x0186, + USB_DEVICE_ID_I6050_2 = 0x0188, }; @@ -234,6 +235,7 @@ struct i2400mu { u8 rx_size_auto_shrink; struct dentry *debugfs_dentry; + unsigned i6050:1; /* 1 if this is a 6050 based SKU */ }; diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 3b48681f8a0..98f4f8c5fb6 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -478,7 +478,16 @@ int i2400mu_probe(struct usb_interface *iface, i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack; i2400m->bus_bm_mac_addr_impaired = 0; - if (id->idProduct == USB_DEVICE_ID_I6050) { + switch (id->idProduct) { + case USB_DEVICE_ID_I6050: + case USB_DEVICE_ID_I6050_2: + i2400mu->i6050 = 1; + break; + default: + break; + } + + if (i2400mu->i6050) { i2400m->bus_fw_names = i2400mu_bus_fw_names_6050; i2400mu->endpoint_cfg.bulk_out = 0; i2400mu->endpoint_cfg.notification = 3; @@ -719,6 +728,7 @@ int i2400mu_post_reset(struct usb_interface *iface) static struct usb_device_id i2400mu_id_table[] = { { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, + { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, { USB_DEVICE(0x8086, 0x0181) }, { USB_DEVICE(0x8086, 0x1403) }, { USB_DEVICE(0x8086, 0x1405) }, -- cgit v1.2.3-70-g09d2 From 26d92f9276a56d55511a427fb70bd70886af647a Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 21 Jan 2010 22:52:08 -0800 Subject: be2net: fix bug in rx page posting Pages are posted to the rxq in such a way that more than one frag can share the page. The last frag that uses the page unmaps the page. In the case when a page is not fully used (due to lack of space in rxq) the last frag that uses the page is not being set as a "last_page_user"; instead, the next frag in the rxq is incorrectly being set. The fix has also been tested on ppc64 with 64k pages... Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 3a1f7902c16..33ab8c7f14f 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -910,7 +910,7 @@ static inline struct page *be_alloc_pages(u32 size) static void be_post_rx_frags(struct be_adapter *adapter) { struct be_rx_page_info *page_info_tbl = adapter->rx_obj.page_info_tbl; - struct be_rx_page_info *page_info = NULL; + struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL; struct be_queue_info *rxq = &adapter->rx_obj.q; struct page *pagep = NULL; struct be_eth_rx_d *rxd; @@ -941,7 +941,6 @@ static void be_post_rx_frags(struct be_adapter *adapter) rxd = queue_head_node(rxq); rxd->fragpa_lo = cpu_to_le32(frag_dmaaddr & 0xFFFFFFFF); rxd->fragpa_hi = cpu_to_le32(upper_32_bits(frag_dmaaddr)); - queue_head_inc(rxq); /* Any space left in the current big page for another frag? */ if ((page_offset + rx_frag_size + rx_frag_size) > @@ -949,10 +948,13 @@ static void be_post_rx_frags(struct be_adapter *adapter) pagep = NULL; page_info->last_page_user = true; } + + prev_page_info = page_info; + queue_head_inc(rxq); page_info = &page_info_tbl[rxq->head]; } if (pagep) - page_info->last_page_user = true; + prev_page_info->last_page_user = true; if (posted) { atomic_add(posted, &rxq->used); -- cgit v1.2.3-70-g09d2 From 60abe78279568a7109db2bcbc71131766a91c2e5 Mon Sep 17 00:00:00 2001 From: Ron Murray Date: Tue, 19 Jan 2010 08:02:48 +0000 Subject: Please add support for Microsoft MN-120 PCMCIA network card Please add support for Microsoft MN-120 PCMCIA network card. It's an old card, I know, but adding support is very easy. You just need to get tulip_core.c to recognise its vendor/device ID. Patch for kernel 2.6.32.4 (and many previous) attached. .....Ron Murray Signed-off-by: Ron Murray Signed-off-by: David S. Miller --- drivers/net/tulip/tulip_core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 595777dcadb..20696b5d60a 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -249,6 +249,7 @@ static struct pci_device_id tulip_pci_tbl[] = { { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */ { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */ + { 0x1414, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Microsoft MN-120 */ { 0x1414, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { } /* terminate list */ }; -- cgit v1.2.3-70-g09d2 From fa4281bbbcb44d1f8bdac894ad0696535272cc43 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 21 Jan 2010 22:51:36 +0000 Subject: be2net: swap only first 2 fields of mcc_wrb Only the first two fields of mcc wrb - embedded, payload_len need to be cpu_to_le32() swapped while issuing a cmd to the hw. The fields tag0, tag1 are opaque and returned back to cpu as is... Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 102ade13416..fee6eee7ae5 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -286,7 +286,7 @@ static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, MCC_WRB_SGE_CNT_SHIFT; wrb->payload_length = payload_len; wrb->tag0 = opcode; - be_dws_cpu_to_le(wrb, 20); + be_dws_cpu_to_le(wrb, 8); } /* Don't touch the hdr after it's prepared */ -- cgit v1.2.3-70-g09d2 From 33d7959a7a9ef36573bfd0cc85ebef29ed4b846d Mon Sep 17 00:00:00 2001 From: Ken Kawasaki Date: Fri, 22 Jan 2010 11:56:25 +0000 Subject: fmvj18x_cs: add new id (Panasonic lan & modem card) fmvj18x_cs, serial_cs: add new id Panasonic lan & modem card (model name:AL-VML101) Signed-off-by: Ken Kawasaki Signed-off-by: David S. Miller --- drivers/net/pcmcia/fmvj18x_cs.c | 1 + drivers/serial/serial_cs.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 813aca3fc43..7b17404d085 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -717,6 +717,7 @@ static struct pcmcia_device_id fmvj18x_ids[] = { PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0e01), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101), PCMCIA_DEVICE_NULL, diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index df854401af2..95421fa3b30 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -758,6 +758,7 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f), PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed), PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf), + PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0e01), PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05), PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101), PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070), -- cgit v1.2.3-70-g09d2 From 9926146b15fd96d78a4f7c32e7a26d50639369f4 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 22 Jan 2010 22:56:16 +0000 Subject: e1000/e1000e: don't use small hardware rx buffers When testing the "e1000: enhance frame fragment detection" (and e1000e) patches we found some bugs with reducing the MTU size. The 1024 byte descriptor used with the 1000 mtu test also (re) introduced the (originally) reported bug, and causes us to need the e1000_clean_tx_irq "enhance frame fragment detection" fix. So what has occured here is that 2.6.32 is only vulnerable for mtu < 1500 due to the jumbo specific routines in both e1000 and e1000e. So, 2.6.32 needs the 2kB buffer len fix for those smaller MTUs, but is not vulnerable to the original issue reported. It has been pointed out that this vulnerability needs to be patched in older kernels that don't have the e1000 jumbo routine. Without the jumbo routines, we need the "enhance frame fragment detection" fix the e1000, old e1000e is only vulnerable for < 1500 mtu, and needs a similar fix. We split the patches up to provide easy backport paths. There is only a slight bit of extra code when this fix and the original "enhance frame fragment detection" fixes are applied, so please apply both, even though it is a bit of overkill. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 20 +------------------- drivers/net/e1000e/netdev.c | 20 +------------------- 2 files changed, 2 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index a53a2017c53..d29bb532ecc 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1698,18 +1698,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; switch (adapter->rx_buffer_len) { - case E1000_RXBUFFER_256: - rctl |= E1000_RCTL_SZ_256; - rctl &= ~E1000_RCTL_BSEX; - break; - case E1000_RXBUFFER_512: - rctl |= E1000_RCTL_SZ_512; - rctl &= ~E1000_RCTL_BSEX; - break; - case E1000_RXBUFFER_1024: - rctl |= E1000_RCTL_SZ_1024; - rctl &= ~E1000_RCTL_BSEX; - break; case E1000_RXBUFFER_2048: default: rctl |= E1000_RCTL_SZ_2048; @@ -3176,13 +3164,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) * however with the new *_jumbo_rx* routines, jumbo receives will use * fragmented skbs */ - if (max_frame <= E1000_RXBUFFER_256) - adapter->rx_buffer_len = E1000_RXBUFFER_256; - else if (max_frame <= E1000_RXBUFFER_512) - adapter->rx_buffer_len = E1000_RXBUFFER_512; - else if (max_frame <= E1000_RXBUFFER_1024) - adapter->rx_buffer_len = E1000_RXBUFFER_1024; - else if (max_frame <= E1000_RXBUFFER_2048) + if (max_frame <= E1000_RXBUFFER_2048) adapter->rx_buffer_len = E1000_RXBUFFER_2048; else #if (PAGE_SIZE >= E1000_RXBUFFER_16384) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 1ea395b6c99..3d887104a0d 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2350,18 +2350,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; switch (adapter->rx_buffer_len) { - case 256: - rctl |= E1000_RCTL_SZ_256; - rctl &= ~E1000_RCTL_BSEX; - break; - case 512: - rctl |= E1000_RCTL_SZ_512; - rctl &= ~E1000_RCTL_BSEX; - break; - case 1024: - rctl |= E1000_RCTL_SZ_1024; - rctl &= ~E1000_RCTL_BSEX; - break; case 2048: default: rctl |= E1000_RCTL_SZ_2048; @@ -4334,13 +4322,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) * fragmented skbs */ - if (max_frame <= 256) - adapter->rx_buffer_len = 256; - else if (max_frame <= 512) - adapter->rx_buffer_len = 512; - else if (max_frame <= 1024) - adapter->rx_buffer_len = 1024; - else if (max_frame <= 2048) + if (max_frame <= 2048) adapter->rx_buffer_len = 2048; else adapter->rx_buffer_len = 4096; -- cgit v1.2.3-70-g09d2 From 8581145f39c39b00cd1b6a2dcb4ce5bf7d8d6070 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 23 Jan 2010 01:35:00 -0800 Subject: igb/igbvf: cleanup exception handling in tx_map_adv After removing the skb_dma_map/unmap calls the exception handling in igb_tx_map_adv is not correct. The issue is that the count value was not being correctly handled so as a result we were not rewinding the ring as back as we should have been. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 2 +- drivers/net/igbvf/netdev.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 933c64ff246..2ca173453b6 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3584,6 +3584,7 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb, for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { struct skb_frag_struct *frag; + count++; i++; if (i == tx_ring->count) i = 0; @@ -3605,7 +3606,6 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb, if (pci_dma_mapping_error(pdev, buffer_info->dma)) goto dma_error; - count++; } tx_ring->buffer_info[i].skb = skb; diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 10e038adba0..43c8375f111 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -2126,6 +2126,7 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter, for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { struct skb_frag_struct *frag; + count++; i++; if (i == tx_ring->count) i = 0; @@ -2146,7 +2147,6 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter, PCI_DMA_TODEVICE); if (pci_dma_mapping_error(pdev, buffer_info->dma)) goto dma_error; - count++; } tx_ring->buffer_info[i].skb = skb; -- cgit v1.2.3-70-g09d2 From 8e1e8a4779cb23c1d9f51e9223795e07ec54d77a Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Sat, 23 Jan 2010 02:02:21 -0800 Subject: net: Fix IPv6 GSO type checks in Intel ethernet drivers Found this problem when testing IPv6 from a KVM guest to a remote host via e1000e device on the host. The following patch fixes the check for IPv6 GSO packet in Intel ethernet drivers to use skb_is_gso_v6(). SKB_GSO_DODGY is also set when packets are forwarded from a guest. Signed-off-by: Sridhar Samudrala Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 2 +- drivers/net/igb/igb_main.c | 2 +- drivers/net/igbvf/netdev.c | 2 +- drivers/net/ixgbe/ixgbe_main.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 3d887104a0d..57f149b75fb 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3786,7 +3786,7 @@ static int e1000_tso(struct e1000_adapter *adapter, 0, IPPROTO_TCP, 0); cmd_length = E1000_TXD_CMD_IP; ipcse = skb_transport_offset(skb) - 1; - } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { + } else if (skb_is_gso_v6(skb)) { ipv6_hdr(skb)->payload_len = 0; tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 2ca173453b6..997124d2992 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3422,7 +3422,7 @@ static inline int igb_tso_adv(struct igb_ring *tx_ring, iph->daddr, 0, IPPROTO_TCP, 0); - } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { + } else if (skb_is_gso_v6(skb)) { ipv6_hdr(skb)->payload_len = 0; tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 43c8375f111..297a5ddd77f 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -1963,7 +1963,7 @@ static int igbvf_tso(struct igbvf_adapter *adapter, iph->daddr, 0, IPPROTO_TCP, 0); - } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { + } else if (skb_is_gso_v6(skb)) { ipv6_hdr(skb)->payload_len = 0; tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 6d61add27a0..b5f64ad6797 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4928,7 +4928,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, iph->daddr, 0, IPPROTO_TCP, 0); - } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { + } else if (skb_is_gso_v6(skb)) { ipv6_hdr(skb)->payload_len = 0; tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, -- cgit v1.2.3-70-g09d2 From 2ca4231de7f7a5fd7137bac152030ba71f15e8c3 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Sat, 23 Jan 2010 02:09:26 -0800 Subject: sky2: Enable/disable WOL per hardware device Y2_HW_WOL_ON/Y2_HW_WOL_OFF should be set and cleared per chip, not per port. On dual port cards, Y2_HW_WOL_ON should be enabled if either sky2 port has WOL enabled. Found while reviewing code for a WOL regression, though this is probably not the cause of the regression. Signed-off-by: Mike McCormack Signed-off-by: David S. Miller --- drivers/net/sky2.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 37f486b65f6..02d0b42e436 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3228,6 +3228,27 @@ static inline u8 sky2_wol_supported(const struct sky2_hw *hw) return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0; } +static void sky2_hw_set_wol(struct sky2_hw *hw) +{ + int wol = 0; + int i; + + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; + struct sky2_port *sky2 = netdev_priv(dev); + + if (sky2->wol) + wol = 1; + } + + if (hw->chip_id == CHIP_ID_YUKON_EC_U || + hw->chip_id == CHIP_ID_YUKON_EX || + hw->chip_id == CHIP_ID_YUKON_FE_P) + sky2_write32(hw, B0_CTST, wol ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); + + device_set_wakeup_enable(&hw->pdev->dev, wol); +} + static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { const struct sky2_port *sky2 = netdev_priv(dev); @@ -3247,13 +3268,7 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) sky2->wol = wol->wolopts; - if (hw->chip_id == CHIP_ID_YUKON_EC_U || - hw->chip_id == CHIP_ID_YUKON_EX || - hw->chip_id == CHIP_ID_YUKON_FE_P) - sky2_write32(hw, B0_CTST, sky2->wol - ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); - - device_set_wakeup_enable(&hw->pdev->dev, sky2->wol); + sky2_hw_set_wol(hw); if (!netif_running(dev)) sky2_wol_init(sky2); -- cgit v1.2.3-70-g09d2 From a348c84d953f61c776e53cde0a63a4e407a23c18 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 21 Jan 2010 16:50:30 -0500 Subject: drm/radeon/kms/atom: fix crtc lock ordering This makes crtc_prepare and crtc_commit match. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index e098bd0cbd2..7af5c1f7b6d 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -782,8 +782,8 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, static void atombios_crtc_prepare(struct drm_crtc *crtc) { - atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); atombios_lock_crtc(crtc, 1); + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); } static void atombios_crtc_commit(struct drm_crtc *crtc) -- cgit v1.2.3-70-g09d2 From fc10332b8ac5ca32d11f898027d84c007543bd80 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 19 Jan 2010 17:16:10 -0500 Subject: drm/radeon/kms: clean up pll struct - add a new flag for fixed post div - pull the pll flags into the struct Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 35 ++++++++++++++--------------- drivers/gpu/drm/radeon/radeon_display.c | 35 ++++++++++++++++------------- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 14 ++++++------ drivers/gpu/drm/radeon/radeon_mode.h | 27 +++++++++++++++------- 4 files changed, 62 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 7af5c1f7b6d..7a8cdf2813d 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -426,7 +426,11 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) uint32_t adjusted_clock; uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; struct radeon_pll *pll; - int pll_flags = 0; + + if (radeon_crtc->crtc_id == 0) + pll = &rdev->clock.p1pll; + else + pll = &rdev->clock.p2pll; memset(&args, 0, sizeof(args)); @@ -434,20 +438,20 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) if ((rdev->family == CHIP_RS600) || (rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) - pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV | - RADEON_PLL_PREFER_CLOSEST_LOWER); + pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV | + RADEON_PLL_PREFER_CLOSEST_LOWER); if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ - pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; + pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; else - pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; + pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; } else { - pll_flags |= RADEON_PLL_LEGACY; + pll->flags |= RADEON_PLL_LEGACY; if (mode->clock > 200000) /* range limits??? */ - pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; + pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; else - pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; + pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; } @@ -456,10 +460,10 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) if (!ASIC_IS_AVIVO(rdev)) { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) - pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; + pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) - pll_flags |= RADEON_PLL_USE_REF_DIV; + pll->flags |= RADEON_PLL_USE_REF_DIV; } radeon_encoder = to_radeon_encoder(encoder); break; @@ -494,23 +498,18 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) adjusted_clock = mode->clock; } - if (radeon_crtc->crtc_id == 0) - pll = &rdev->clock.p1pll; - else - pll = &rdev->clock.p2pll; - if (ASIC_IS_AVIVO(rdev)) { if (radeon_new_pll) radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, - &ref_div, &post_div, pll_flags); + &ref_div, &post_div); else radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, - &ref_div, &post_div, pll_flags); + &ref_div, &post_div); } else radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, - &ref_div, &post_div, pll_flags); + &ref_div, &post_div); index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index f899320f0a6..6a92f994cc2 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -411,11 +411,12 @@ void radeon_compute_pll(struct radeon_pll *pll, uint32_t *fb_div_p, uint32_t *frac_fb_div_p, uint32_t *ref_div_p, - uint32_t *post_div_p, - int flags) + uint32_t *post_div_p) { uint32_t min_ref_div = pll->min_ref_div; uint32_t max_ref_div = pll->max_ref_div; + uint32_t min_post_div = pll->min_post_div; + uint32_t max_post_div = pll->max_post_div; uint32_t min_fractional_feed_div = 0; uint32_t max_fractional_feed_div = 0; uint32_t best_vco = pll->best_vco; @@ -431,7 +432,7 @@ void radeon_compute_pll(struct radeon_pll *pll, DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div); freq = freq * 1000; - if (flags & RADEON_PLL_USE_REF_DIV) + if (pll->flags & RADEON_PLL_USE_REF_DIV) min_ref_div = max_ref_div = pll->reference_div; else { while (min_ref_div < max_ref_div-1) { @@ -446,19 +447,22 @@ void radeon_compute_pll(struct radeon_pll *pll, } } - if (flags & RADEON_PLL_USE_FRAC_FB_DIV) { + if (pll->flags & RADEON_PLL_USE_POST_DIV) + min_post_div = max_post_div = pll->post_div; + + if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { min_fractional_feed_div = pll->min_frac_feedback_div; max_fractional_feed_div = pll->max_frac_feedback_div; } - for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) { + for (post_div = min_post_div; post_div <= max_post_div; ++post_div) { uint32_t ref_div; - if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) + if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) continue; /* legacy radeons only have a few post_divs */ - if (flags & RADEON_PLL_LEGACY) { + if (pll->flags & RADEON_PLL_LEGACY) { if ((post_div == 5) || (post_div == 7) || (post_div == 9) || @@ -505,7 +509,7 @@ void radeon_compute_pll(struct radeon_pll *pll, tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div; current_freq = radeon_div(tmp, ref_div * post_div); - if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) { + if (pll->flags & RADEON_PLL_PREFER_CLOSEST_LOWER) { error = freq - current_freq; error = error < 0 ? 0xffffffff : error; } else @@ -532,12 +536,12 @@ void radeon_compute_pll(struct radeon_pll *pll, best_freq = current_freq; best_error = error; best_vco_diff = vco_diff; - } else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) || - ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) || - ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) || - ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) || - ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) || - ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) { + } else if (((pll->flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) || + ((pll->flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) || + ((pll->flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) || + ((pll->flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) || + ((pll->flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) || + ((pll->flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) { best_post_div = post_div; best_ref_div = ref_div; best_feedback_div = feedback_div; @@ -573,8 +577,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, uint32_t *fb_div_p, uint32_t *frac_fb_div_p, uint32_t *ref_div_p, - uint32_t *post_div_p, - int flags) + uint32_t *post_div_p) { fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq; fixed20_12 pll_out_max, pll_out_min; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 762e07b0895..b6d8081e124 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -692,7 +692,6 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) uint32_t post_divider = 0; uint32_t freq = 0; uint8_t pll_gain; - int pll_flags = RADEON_PLL_LEGACY; bool use_bios_divs = false; /* PLL registers */ uint32_t pll_ref_div = 0; @@ -726,10 +725,12 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) else pll = &rdev->clock.p1pll; + pll->flags = RADEON_PLL_LEGACY; + if (mode->clock > 200000) /* range limits??? */ - pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; + pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; else - pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; + pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc == crtc) { @@ -741,7 +742,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) } if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) - pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; + pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { if (!rdev->is_atom_bios) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -756,7 +757,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) } } } - pll_flags |= RADEON_PLL_USE_REF_DIV; + pll->flags |= RADEON_PLL_USE_REF_DIV; } } } @@ -766,8 +767,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) if (!use_bios_divs) { radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &frac_fb_div, - &reference_div, &post_divider, - pll_flags); + &reference_div, &post_divider); for (post_div = &post_divs[0]; post_div->divider; ++post_div) { if (post_div->divider == post_divider) diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index eb19b3022b0..96b851f92f4 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -125,16 +125,24 @@ struct radeon_tmds_pll { #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9) #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) +#define RADEON_PLL_USE_POST_DIV (1 << 12) struct radeon_pll { - uint16_t reference_freq; - uint16_t reference_div; + /* reference frequency */ + uint32_t reference_freq; + + /* fixed dividers */ + uint32_t reference_div; + uint32_t post_div; + + /* pll in/out limits */ uint32_t pll_in_min; uint32_t pll_in_max; uint32_t pll_out_min; uint32_t pll_out_max; - uint16_t xclk; + uint32_t best_vco; + /* divider limits */ uint32_t min_ref_div; uint32_t max_ref_div; uint32_t min_post_div; @@ -143,7 +151,12 @@ struct radeon_pll { uint32_t max_feedback_div; uint32_t min_frac_feedback_div; uint32_t max_frac_feedback_div; - uint32_t best_vco; + + /* flags for the current clock */ + uint32_t flags; + + /* pll id */ + uint32_t id; }; struct radeon_i2c_chan { @@ -417,8 +430,7 @@ extern void radeon_compute_pll(struct radeon_pll *pll, uint32_t *fb_div_p, uint32_t *frac_fb_div_p, uint32_t *ref_div_p, - uint32_t *post_div_p, - int flags); + uint32_t *post_div_p); extern void radeon_compute_pll_avivo(struct radeon_pll *pll, uint64_t freq, @@ -426,8 +438,7 @@ extern void radeon_compute_pll_avivo(struct radeon_pll *pll, uint32_t *fb_div_p, uint32_t *frac_fb_div_p, uint32_t *ref_div_p, - uint32_t *post_div_p, - int flags); + uint32_t *post_div_p); extern void radeon_setup_encoder_clones(struct drm_device *dev); -- cgit v1.2.3-70-g09d2 From 4eaeca33512b9774c25507b9a9bdcfe3791a5cc5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 19 Jan 2010 17:32:27 -0500 Subject: drm/radeon/kms: clean up atombios pll code - split pll adjust into a separate function - use a union for SetPixelClock params Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 196 ++++++++++++++++++++------------- 1 file changed, 121 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 7a8cdf2813d..e619aca5423 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -409,30 +409,22 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) } } -void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) +union adjust_pixel_clock { + ADJUST_DISPLAY_PLL_PS_ALLOCATION v1; +}; + +static u32 atombios_adjust_pll(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct radeon_pll *pll) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; struct drm_encoder *encoder = NULL; struct radeon_encoder *radeon_encoder = NULL; - uint8_t frev, crev; - int index; - SET_PIXEL_CLOCK_PS_ALLOCATION args; - PIXEL_CLOCK_PARAMETERS *spc1_ptr; - PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr; - PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr; - uint32_t pll_clock = mode->clock; - uint32_t adjusted_clock; - uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; - struct radeon_pll *pll; + u32 adjusted_clock = mode->clock; - if (radeon_crtc->crtc_id == 0) - pll = &rdev->clock.p1pll; - else - pll = &rdev->clock.p2pll; - - memset(&args, 0, sizeof(args)); + /* reset the pll flags */ + pll->flags = 0; if (ASIC_IS_AVIVO(rdev)) { if ((rdev->family == CHIP_RS600) || @@ -457,15 +449,17 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc == crtc) { - if (!ASIC_IS_AVIVO(rdev)) { - if (encoder->encoder_type != - DRM_MODE_ENCODER_DAC) + radeon_encoder = to_radeon_encoder(encoder); + if (ASIC_IS_AVIVO(rdev)) { + /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ + if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) + adjusted_clock = mode->clock * 2; + } else { + if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; - if (encoder->encoder_type == - DRM_MODE_ENCODER_LVDS) + if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) pll->flags |= RADEON_PLL_USE_REF_DIV; } - radeon_encoder = to_radeon_encoder(encoder); break; } } @@ -475,28 +469,88 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) * special hw requirements. */ if (ASIC_IS_DCE3(rdev)) { - ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args; - - if (!encoder) - return; + union adjust_pixel_clock args; + struct radeon_encoder_atom_dig *dig; + u8 frev, crev; + int index; - memset(&adjust_pll_args, 0, sizeof(adjust_pll_args)); - adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10); - adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id; - adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder); + if (!radeon_encoder->enc_priv) + return adjusted_clock; + dig = radeon_encoder->enc_priv; index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); - atom_execute_table(rdev->mode_info.atom_context, - index, (uint32_t *)&adjust_pll_args); - adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10; - } else { - /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ - if (ASIC_IS_AVIVO(rdev) && - (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)) - adjusted_clock = mode->clock * 2; - else - adjusted_clock = mode->clock; + atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, + &crev); + + memset(&args, 0, sizeof(args)); + + switch (frev) { + case 1: + switch (crev) { + case 1: + case 2: + args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); + args.v1.ucTransmitterID = radeon_encoder->encoder_id; + args.v1.ucEncodeMode = atombios_get_encoder_mode(encoder); + + atom_execute_table(rdev->mode_info.atom_context, + index, (uint32_t *)&args); + adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10; + break; + default: + DRM_ERROR("Unknown table version %d %d\n", frev, crev); + return adjusted_clock; + } + break; + default: + DRM_ERROR("Unknown table version %d %d\n", frev, crev); + return adjusted_clock; + } } + return adjusted_clock; +} + +union set_pixel_clock { + SET_PIXEL_CLOCK_PS_ALLOCATION base; + PIXEL_CLOCK_PARAMETERS v1; + PIXEL_CLOCK_PARAMETERS_V2 v2; + PIXEL_CLOCK_PARAMETERS_V3 v3; +}; + +void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct drm_encoder *encoder = NULL; + struct radeon_encoder *radeon_encoder = NULL; + u8 frev, crev; + int index; + union set_pixel_clock args; + u32 pll_clock = mode->clock; + u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; + struct radeon_pll *pll; + u32 adjusted_clock; + + memset(&args, 0, sizeof(args)); + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc == crtc) { + radeon_encoder = to_radeon_encoder(encoder); + break; + } + } + + if (!radeon_encoder) + return; + + if (radeon_crtc->crtc_id == 0) + pll = &rdev->clock.p1pll; + else + pll = &rdev->clock.p2pll; + + /* adjust pixel clock as needed */ + adjusted_clock = atombios_adjust_pll(crtc, mode, pll); if (ASIC_IS_AVIVO(rdev)) { if (radeon_new_pll) @@ -519,45 +573,38 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) case 1: switch (crev) { case 1: - spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput; - spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); - spc1_ptr->usRefDiv = cpu_to_le16(ref_div); - spc1_ptr->usFbDiv = cpu_to_le16(fb_div); - spc1_ptr->ucFracFbDiv = frac_fb_div; - spc1_ptr->ucPostDiv = post_div; - spc1_ptr->ucPpll = + args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); + args.v1.usRefDiv = cpu_to_le16(ref_div); + args.v1.usFbDiv = cpu_to_le16(fb_div); + args.v1.ucFracFbDiv = frac_fb_div; + args.v1.ucPostDiv = post_div; + args.v1.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; - spc1_ptr->ucCRTC = radeon_crtc->crtc_id; - spc1_ptr->ucRefDivSrc = 1; + args.v1.ucCRTC = radeon_crtc->crtc_id; + args.v1.ucRefDivSrc = 1; break; case 2: - spc2_ptr = - (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput; - spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); - spc2_ptr->usRefDiv = cpu_to_le16(ref_div); - spc2_ptr->usFbDiv = cpu_to_le16(fb_div); - spc2_ptr->ucFracFbDiv = frac_fb_div; - spc2_ptr->ucPostDiv = post_div; - spc2_ptr->ucPpll = + args.v2.usPixelClock = cpu_to_le16(mode->clock / 10); + args.v2.usRefDiv = cpu_to_le16(ref_div); + args.v2.usFbDiv = cpu_to_le16(fb_div); + args.v2.ucFracFbDiv = frac_fb_div; + args.v2.ucPostDiv = post_div; + args.v2.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; - spc2_ptr->ucCRTC = radeon_crtc->crtc_id; - spc2_ptr->ucRefDivSrc = 1; + args.v2.ucCRTC = radeon_crtc->crtc_id; + args.v2.ucRefDivSrc = 1; break; case 3: - if (!encoder) - return; - spc3_ptr = - (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput; - spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); - spc3_ptr->usRefDiv = cpu_to_le16(ref_div); - spc3_ptr->usFbDiv = cpu_to_le16(fb_div); - spc3_ptr->ucFracFbDiv = frac_fb_div; - spc3_ptr->ucPostDiv = post_div; - spc3_ptr->ucPpll = + args.v3.usPixelClock = cpu_to_le16(mode->clock / 10); + args.v3.usRefDiv = cpu_to_le16(ref_div); + args.v3.usFbDiv = cpu_to_le16(fb_div); + args.v3.ucFracFbDiv = frac_fb_div; + args.v3.ucPostDiv = post_div; + args.v3.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; - spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2); - spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id; - spc3_ptr->ucEncoderMode = + args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2); + args.v3.ucTransmitterId = radeon_encoder->encoder_id; + args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder); break; default: @@ -570,7 +617,6 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) return; } - printk("executing set pll\n"); atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } -- cgit v1.2.3-70-g09d2 From 947bfc83043181e86e3e3134da158e479c9bcc51 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 21 Jan 2010 17:14:49 -0500 Subject: drm/radeon/kms/atom: atom parser fixes Only reset the reg block on the initial execute table call; nested calls require the reg block not be reset on each call. Also reset the fb window and io mode. This matches the upstream parser behavior. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atom.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index cf3126108a4..e3b44562d26 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -1122,8 +1122,6 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3 SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps); - /* reset reg block */ - ctx->reg_block = 0; ectx.ctx = ctx; ectx.ps_shift = ps / 4; ectx.start = base; @@ -1160,6 +1158,12 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3 void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) { mutex_lock(&ctx->mutex); + /* reset reg block */ + ctx->reg_block = 0; + /* reset fb window */ + ctx->fb_base = 0; + /* reset io mode */ + ctx->io_mode = ATOM_IO_MM; atom_execute_table_locked(ctx, index, params); mutex_unlock(&ctx->mutex); } -- cgit v1.2.3-70-g09d2 From 38678d3557420a1c40f7ad5a04a46a7de7a305b9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 21 Jan 2010 19:28:18 -0500 Subject: drm/radeon/kms: fix legacy get_engine/memory clock Fix a bad shift in the post div. Should fix fdo bug 26145 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_clocks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index 812f24dbc2a..73c4405bf42 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -56,7 +56,7 @@ uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev) else if (post_div == 3) sclk >>= 2; else if (post_div == 4) - sclk >>= 4; + sclk >>= 3; return sclk; } @@ -86,7 +86,7 @@ uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) else if (post_div == 3) mclk >>= 2; else if (post_div == 4) - mclk >>= 4; + mclk >>= 3; return mclk; } -- cgit v1.2.3-70-g09d2 From a1ee06b72968d80ab9362ec61143c4f090cc2d1b Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Thu, 21 Jan 2010 18:55:32 +0100 Subject: i2c: mxc: let time to generate stop bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After generating the stop bit by changing MSTA from 1 to 0, the i2c_imx->stopped was immediatly set to 1. The second test on i2c_imx->stopped then is correct and the controller never waits if the bus is busy. This patch corrects this. On mx31moboard, stop bit was not generated on single write transfers. This was kept unnoticed as other transfers are made afterwards that help the write recipient to resynchronize. Thanks to Philippe and Michael for the debugging. Signed-off-by: Valentin Longchamp Signed-off by: Philippe Rétornaz Reported-by: Michael Bonani Acked-by; Wolfram Sang Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-imx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index e3654d683e1..602b30e32cf 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -226,7 +226,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) temp = readb(i2c_imx->base + IMX_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); writeb(temp, i2c_imx->base + IMX_I2C_I2CR); - i2c_imx->stopped = 1; } if (cpu_is_mx1()) { /* @@ -236,8 +235,10 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) udelay(i2c_imx->disable_delay); } - if (!i2c_imx->stopped) + if (!i2c_imx->stopped) { i2c_imx_bus_busy(i2c_imx, 0); + i2c_imx->stopped = 1; + } /* Disable I2C controller */ writeb(0, i2c_imx->base + IMX_I2C_I2CR); -- cgit v1.2.3-70-g09d2 From 4927fbf11dc1057cd9c94dd40358e5f98c999311 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 8 Jan 2010 17:23:17 +0100 Subject: i2c: imx: call ioremap only after request_mem_region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit accordingly adapt order of release_mem_region and release_mem_region on remove. Signed-off-by: Uwe Kleine-König Cc: Ben Dooks Cc: Wolfram Sang Cc: Richard Zhao Cc: Darius Augulis Cc: Sascha Hauer Cc: linux-i2c@vger.kernel.org Acked-by: Wolfram Sang Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-imx.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 602b30e32cf..75bf820e7cc 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -497,22 +497,23 @@ static int __init i2c_imx_probe(struct platform_device *pdev) } res_size = resource_size(res); + + if (!request_mem_region(res->start, res_size, DRIVER_NAME)) { + ret = -EBUSY; + goto fail0; + } + base = ioremap(res->start, res_size); if (!base) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -EIO; - goto fail0; + goto fail1; } i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL); if (!i2c_imx) { dev_err(&pdev->dev, "can't allocate interface\n"); ret = -ENOMEM; - goto fail1; - } - - if (!request_mem_region(res->start, res_size, DRIVER_NAME)) { - ret = -EBUSY; goto fail2; } @@ -583,11 +584,11 @@ fail5: fail4: clk_put(i2c_imx->clk); fail3: - release_mem_region(i2c_imx->res->start, resource_size(res)); -fail2: kfree(i2c_imx); -fail1: +fail2: iounmap(base); +fail1: + release_mem_region(res->start, resource_size(res)); fail0: if (pdata && pdata->exit) pdata->exit(&pdev->dev); @@ -619,8 +620,8 @@ static int __exit i2c_imx_remove(struct platform_device *pdev) clk_put(i2c_imx->clk); - release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res)); iounmap(i2c_imx->base); + release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res)); kfree(i2c_imx); return 0; } -- cgit v1.2.3-70-g09d2 From a1470890f29da73783e932078ed911f5871e3ad3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 18 Jan 2010 11:42:37 +1000 Subject: drm/nouveau: report LVDS as disconnected if lid closed Also adds a module option to ignore the status reported via ACPI, in case we hit systems with broken ACPI. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_connector.c | 7 +++++++ drivers/gpu/drm/nouveau/nouveau_drv.c | 4 ++++ drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + 3 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 8da35281a0c..7e6d673f3a2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -24,9 +24,12 @@ * */ +#include + #include "drmP.h" #include "drm_edid.h" #include "drm_crtc_helper.h" + #include "nouveau_reg.h" #include "nouveau_drv.h" #include "nouveau_encoder.h" @@ -235,6 +238,10 @@ nouveau_connector_detect(struct drm_connector *connector) if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); if (nv_encoder && nv_connector->native_mode) { +#ifdef CONFIG_ACPI + if (!nouveau_ignorelid && !acpi_lid_open()) + return connector_status_disconnected; +#endif nouveau_connector_set_encoder(connector, nv_encoder); return connector_status_connected; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 06eb993e088..343ab7f17cc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -71,6 +71,10 @@ MODULE_PARM_DESC(uscript_tmds, "TMDS output script table ID (>=GeForce 8)"); int nouveau_uscript_tmds = -1; module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400); +MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status"); +int nouveau_ignorelid = 0; +module_param_named(ignorelid, nouveau_ignorelid, int, 0400); + MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n" "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n" diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index cc36866e2a9..6b9690418bc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -677,6 +677,7 @@ extern char *nouveau_tv_norm; extern int nouveau_reg_debug; extern char *nouveau_vbios; extern int nouveau_ctxfw; +extern int nouveau_ignorelid; /* nouveau_state.c */ extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); -- cgit v1.2.3-70-g09d2 From 0208843dd59330c30e0773c77d5362260aa340e0 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 21 Jan 2010 15:03:23 +1000 Subject: drm/nouveau: fix failure path if userspace specifies no valid memtypes We need to add the buffer to the list even if we fail, otherwise the validate_fini() call won't unreserve + unreference the GEM object, making TTM very unhappy. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_gem.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 50483304408..6ac804b0c9f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -321,6 +321,7 @@ retry: else { NV_ERROR(dev, "invalid valid domains: 0x%08x\n", b->valid_domains); + list_add_tail(&nvbo->entry, &op->both_list); validate_fini(op, NULL); return -EINVAL; } -- cgit v1.2.3-70-g09d2 From 0107bae01add219e1a146f2b412d64a7f1946028 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 22 Jan 2010 09:10:05 +1000 Subject: drm/nv50: fail auxch transaction if reply count not what we expect Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_dp.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 9e2926c4857..dd493722422 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -490,7 +490,8 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, if (!nv_wait(NV50_AUXCH_CTRL(index), 0x00010000, 0x00000000)) { NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", nv_rd32(dev, NV50_AUXCH_CTRL(index))); - return -EBUSY; + ret = -EBUSY; + goto out; } udelay(400); @@ -501,6 +502,11 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, break; } + if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) { + ret = -EREMOTEIO; + goto out; + } + if (cmd & 1) { for (i = 0; i < 4; i++) { data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); -- cgit v1.2.3-70-g09d2 From 162265367a96d381f07066581d65e52627b08618 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 22 Jan 2010 10:57:01 +1000 Subject: drm/nv50: prevent switching off SOR when in use for DVI-over-DP Another hack because of us exposing each encoder block's function as an encoder rather than exposing a single encoder that deals with them all. A proper fix will come, it's just rather invasive so this hack will do until then. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_sor.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index e395c16d30f..ecf1936b822 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c @@ -90,11 +90,24 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_encoder *enc; uint32_t val; int or = nv_encoder->or; NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); + nv_encoder->last_dpms = mode; + list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { + struct nouveau_encoder *nvenc = nouveau_encoder(enc); + + if (nvenc == nv_encoder || + nvenc->dcb->or != nv_encoder->dcb->or) + continue; + + if (nvenc->last_dpms == DRM_MODE_DPMS_ON) + return; + } + /* wait for it to be done */ if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or), NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) { -- cgit v1.2.3-70-g09d2 From 1a961ce09fe39df9a1b796df98794fd32c76c413 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Wed, 20 Jan 2010 20:01:30 +0100 Subject: drm/ttm: Fix race condition in ttm_bo_delayed_delete (v3, final) Resending this with Thomas Hellstrom's signoff for merging into 2.6.33 ttm_bo_delayed_delete has a race condition, because after we do: kref_put(&nentry->list_kref, ttm_bo_release_list); we are not holding the list lock and not holding any reference to objects, and thus every bo in the list can be removed and freed at this point. However, we then use the next pointer we stored, which is not guaranteed to be valid. This was apparently the cause of some Nouveau oopses I experienced. This patch rewrites the function so that it keeps the reference to nentry until nentry itself is freed and we already got a reference to nentry->next. v2 updated by me according to Thomas Hellstrom's feedback. v3 proposed by Thomas Hellstrom. Commit comment updated by me. Both updates fixed minor efficiency/style issues only and all three versions should be correct. Signed-off-by: Luca Barbieri Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 54 +++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index da3702135ad..8036b6e189e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -524,52 +524,44 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all) static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all) { struct ttm_bo_global *glob = bdev->glob; - struct ttm_buffer_object *entry, *nentry; - struct list_head *list, *next; - int ret; + struct ttm_buffer_object *entry = NULL; + int ret = 0; spin_lock(&glob->lru_lock); - list_for_each_safe(list, next, &bdev->ddestroy) { - entry = list_entry(list, struct ttm_buffer_object, ddestroy); - nentry = NULL; + if (list_empty(&bdev->ddestroy)) + goto out_unlock; - /* - * Protect the next list entry from destruction while we - * unlock the lru_lock. - */ + entry = list_first_entry(&bdev->ddestroy, + struct ttm_buffer_object, ddestroy); + kref_get(&entry->list_kref); + + for (;;) { + struct ttm_buffer_object *nentry = NULL; - if (next != &bdev->ddestroy) { - nentry = list_entry(next, struct ttm_buffer_object, - ddestroy); + if (entry->ddestroy.next != &bdev->ddestroy) { + nentry = list_first_entry(&entry->ddestroy, + struct ttm_buffer_object, ddestroy); kref_get(&nentry->list_kref); } - kref_get(&entry->list_kref); spin_unlock(&glob->lru_lock); ret = ttm_bo_cleanup_refs(entry, remove_all); kref_put(&entry->list_kref, ttm_bo_release_list); + entry = nentry; + + if (ret || !entry) + goto out; spin_lock(&glob->lru_lock); - if (nentry) { - bool next_onlist = !list_empty(next); - spin_unlock(&glob->lru_lock); - kref_put(&nentry->list_kref, ttm_bo_release_list); - spin_lock(&glob->lru_lock); - /* - * Someone might have raced us and removed the - * next entry from the list. We don't bother restarting - * list traversal. - */ - - if (!next_onlist) - break; - } - if (ret) + if (list_empty(&entry->ddestroy)) break; } - ret = !list_empty(&bdev->ddestroy); - spin_unlock(&glob->lru_lock); +out_unlock: + spin_unlock(&glob->lru_lock); +out: + if (entry) + kref_put(&entry->list_kref, ttm_bo_release_list); return ret; } -- cgit v1.2.3-70-g09d2 From 0eaddb28d3460f13102cd82cf58af875bfb1bd53 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sat, 16 Jan 2010 16:05:04 +0100 Subject: drm/ttm: Allow system memory as a busy placement. This is needed to fix a vmwgfx memory usage bug. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 8036b6e189e..1a3e909b7bb 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -943,6 +943,14 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, ttm_flag_masked(&cur_flags, placement->busy_placement[i], ~TTM_PL_MASK_MEMTYPE); + + if (mem_type == TTM_PL_SYSTEM) { + mem->mem_type = mem_type; + mem->placement = cur_flags; + mem->mm_node = NULL; + return 0; + } + ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem, interruptible, no_wait); if (ret == 0 && mem->mm_node) { -- cgit v1.2.3-70-g09d2 From 8ba5152a3acd5914cade42a1c8c9dc58ad8d1a89 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sat, 16 Jan 2010 16:05:05 +0100 Subject: drm/vmwgfx: Optimize memory footprint for DMA buffers. Use VRAM whenever there is free space for DMA buffers, but use system GMR memory if using VRAM would cause an eviction. This significantly reduces the guest system memory usage for VMs with a large amount of VRAM allocated. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 9 +++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 19 +++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 2 +- 4 files changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index 37a81925b15..825ebe3d89d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -48,6 +48,15 @@ struct ttm_placement vmw_vram_placement = { .busy_placement = &vram_placement_flags }; +struct ttm_placement vmw_vram_sys_placement = { + .fpfn = 0, + .lpfn = 0, + .num_placement = 1, + .placement = &vram_placement_flags, + .num_busy_placement = 1, + .busy_placement = &sys_placement_flags +}; + struct ttm_placement vmw_vram_ne_placement = { .fpfn = 0, .lpfn = 0, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 7532b9b47ee..50529a7f06f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -404,6 +404,7 @@ extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma); extern struct ttm_placement vmw_vram_placement; extern struct ttm_placement vmw_vram_ne_placement; +extern struct ttm_placement vmw_vram_sys_placement; extern struct ttm_placement vmw_sys_placement; extern struct ttm_bo_driver vmw_bo_driver; extern int vmw_dma_quiescent(struct drm_device *dev); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 2e92da56740..d69caf92ffe 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -487,6 +487,21 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv, { int ret; + if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL) + return 0; + + /** + * Put BO in VRAM, only if there is space. + */ + + ret = ttm_bo_validate(bo, &vmw_vram_sys_placement, true, false); + if (unlikely(ret == -ERESTARTSYS)) + return ret; + + /** + * Otherwise, set it up as GMR. + */ + if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL) return 0; @@ -494,6 +509,10 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv, if (likely(ret == 0 || ret == -ERESTARTSYS)) return ret; + /** + * If that failed, try VRAM again, this time evicting + * previous contents. + */ ret = ttm_bo_validate(bo, &vmw_vram_placement, true, false); return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index e0878077e8a..e01db120eff 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -872,7 +872,7 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, } ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size, - &vmw_vram_placement, true, + &vmw_vram_sys_placement, true, &vmw_user_dmabuf_destroy); if (unlikely(ret != 0)) return ret; -- cgit v1.2.3-70-g09d2 From d796d8446fe0ff4442c1a1d0b10c861f17ac8168 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 25 Jan 2010 13:08:08 +1000 Subject: drm/radeon/kms: make hibernate work on IGPs This is the least invasive fix without migrating the radeon driver to pm_ops from what I can see. We just always migrate VRAM objects on IGPs for now and we can fix it up later to migrate depending on STR vs STD. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_object.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 4e636de877b..d72a71bff21 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -220,7 +220,8 @@ int radeon_bo_unpin(struct radeon_bo *bo) int radeon_bo_evict_vram(struct radeon_device *rdev) { - if (rdev->flags & RADEON_IS_IGP) { + /* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */ + if (0 && (rdev->flags & RADEON_IS_IGP)) { if (rdev->mc.igp_sideport_enabled == false) /* Useless to evict on IGP chips */ return 0; -- cgit v1.2.3-70-g09d2 From 5fd4df4d475a7fee96fff54f6341192f547984e0 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 18 Jan 2010 16:47:04 +0800 Subject: drm: fix regression in fb blank handling commit 731b5a15a3b1474a41c2ca29b4c32b0f21bc852e Author: James Simmons Date: Thu Oct 29 20:39:07 2009 +0000 drm/kms: properly handle fbdev blanking uses DRM_MODE_DPMS_ON for FB_BLANK_NORMAL, but DRM_MODE_DPMS_ON is actually for turning output on instead of blank. This makes fb blank broken on my T61, it put LVDS on but leave pipe disabled which made screen totally white or caused some 'burning' effect. [airlied: James objects to this but at this point in 2.6.33, I can't see a patch that will fix this properly like he wants coming in time and otherwise this is a regression - proper fix for 2.6.34 hopefully.] Cc: James Simmons Signed-off-by: Zhenyu Wang Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1c2b7d44ec0..0f9e90552dc 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -389,7 +389,7 @@ int drm_fb_helper_blank(int blank, struct fb_info *info) break; /* Display: Off; HSync: On, VSync: On */ case FB_BLANK_NORMAL: - drm_fb_helper_off(info, DRM_MODE_DPMS_ON); + drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); break; /* Display: Off; HSync: Off, VSync: On */ case FB_BLANK_HSYNC_SUSPEND: -- cgit v1.2.3-70-g09d2 From f2ab3a13d2cbe19426c27c35a014c98212e914a5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 25 Jan 2010 16:13:12 +1000 Subject: drm/radeon/kms: drop unnecessary printks. These printks aren't required anymore. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index e619aca5423..af464e351fb 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -307,7 +307,6 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc, args.susModeMiscInfo.usAccess = cpu_to_le16(misc); args.ucCRTC = radeon_crtc->crtc_id; - printk("executing set crtc dtd timing\n"); atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } @@ -347,7 +346,6 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, args.susModeMiscInfo.usAccess = cpu_to_le16(misc); args.ucCRTC = radeon_crtc->crtc_id; - printk("executing set crtc timing\n"); atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } -- cgit v1.2.3-70-g09d2 From 7087e16286913b41ba9a5186360645b57b8508dd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 25 Jan 2010 16:13:55 +1000 Subject: drm/radeon/kms: preface warning printk with driver name This just adds a little more info to the warning for old -ati/mesa userspaces. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 9cc4ba8d03d..e4c45ec1650 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -562,7 +562,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } ib[idx+1+i] = track->cb_color0_base_last; - printk_once(KERN_WARNING "You have old & broken userspace " + printk_once(KERN_WARNING "radeon: You have old & broken userspace " "please consider updating mesa & xf86-video-ati\n"); } else { r = r600_cs_packet_next_reloc(p, &reloc); -- cgit v1.2.3-70-g09d2 From a40ccc6868943e74ec12f26a266ce1d0373b2b32 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Sun, 24 Jan 2010 18:46:06 +0000 Subject: sky2: revert config space change Obviously, this register had some other impact that is causing the regression. Either it is masking some other access or needs to be reset in some path. Either, way it is best to just revert the change for 2.6.33 This reverts commit 166a0fd4c788ec7f10ca8194ec6d526afa12db75. Signed-off-by: David S. Miller --- drivers/net/sky2.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 02d0b42e436..d760650c5c0 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -644,6 +644,7 @@ static void sky2_phy_power_up(struct sky2_hw *hw, unsigned port) { u32 reg1; + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); reg1 &= ~phy_power[port]; @@ -651,6 +652,7 @@ static void sky2_phy_power_up(struct sky2_hw *hw, unsigned port) reg1 |= coma_mode[port]; sky2_pci_write32(hw, PCI_DEV_REG1, reg1); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); sky2_pci_read32(hw, PCI_DEV_REG1); if (hw->chip_id == CHIP_ID_YUKON_FE) @@ -707,9 +709,11 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port) gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_PDOWN); } + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); reg1 |= phy_power[port]; /* set PHY to PowerDown/COMA Mode */ sky2_pci_write32(hw, PCI_DEV_REG1, reg1); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); } /* Force a renegotiation */ @@ -2149,7 +2153,9 @@ static void sky2_qlink_intr(struct sky2_hw *hw) /* reset PHY Link Detect */ phy = sky2_pci_read16(hw, PSM_CONFIG_REG4); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); sky2_pci_write16(hw, PSM_CONFIG_REG4, phy | 1); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); sky2_link_up(sky2); } @@ -2640,6 +2646,7 @@ static void sky2_hw_intr(struct sky2_hw *hw) if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) { u16 pci_err; + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); pci_err = sky2_pci_read16(hw, PCI_STATUS); if (net_ratelimit()) dev_err(&pdev->dev, "PCI hardware error (0x%x)\n", @@ -2647,12 +2654,14 @@ static void sky2_hw_intr(struct sky2_hw *hw) sky2_pci_write16(hw, PCI_STATUS, pci_err | PCI_STATUS_ERROR_BITS); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); } if (status & Y2_IS_PCI_EXP) { /* PCI-Express uncorrectable Error occurred */ u32 err; + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS); sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, 0xfffffffful); @@ -2660,6 +2669,7 @@ static void sky2_hw_intr(struct sky2_hw *hw) dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err); sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); } if (status & Y2_HWE_L1_MASK) @@ -3038,6 +3048,7 @@ static void sky2_reset(struct sky2_hw *hw) } sky2_power_on(hw); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); for (i = 0; i < hw->ports; i++) { sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); @@ -3074,6 +3085,7 @@ static void sky2_reset(struct sky2_hw *hw) reg <<= PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE; /* reset PHY Link Detect */ + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); sky2_pci_write16(hw, PSM_CONFIG_REG4, reg | PSM_CONFIG_REG4_RST_PHY_LINK_DETECT); sky2_pci_write16(hw, PSM_CONFIG_REG4, reg); @@ -3091,6 +3103,7 @@ static void sky2_reset(struct sky2_hw *hw) /* restore the PCIe Link Control register */ sky2_pci_write16(hw, cap + PCI_EXP_LNKCTL, reg); } + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); /* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */ sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16)); -- cgit v1.2.3-70-g09d2 From a00d643a2a841e76dfb76ec4f8a1e71844252974 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Mon, 25 Jan 2010 15:00:48 +0100 Subject: hwmon: (smsc47m1) Fix section mismatch smsc47m1_restore is called from sm_smsc47m1_exit, which is an __exit function, so it can't be __init. Signed-off-by: Jeff Mahoney Signed-off-by: Jean Delvare --- drivers/hwmon/smsc47m1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 9ca97818bd4..8fa462f2b57 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -488,7 +488,7 @@ static int __init smsc47m1_find(unsigned short *addr, } /* Restore device to its initial state */ -static void __init smsc47m1_restore(const struct smsc47m1_sio_data *sio_data) +static void smsc47m1_restore(const struct smsc47m1_sio_data *sio_data) { if ((sio_data->activate & 0x01) == 0) { superio_enter(); -- cgit v1.2.3-70-g09d2 From 316e2664dcc82e9c5f73360a4fb8f9279a8152ed Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 25 Jan 2010 15:00:49 +0100 Subject: hwmon: (amc6821) Double unlock bug The mutex gets unlocked after we goto EXIT. Signed-off-by: Dan Carpenter Signed-off-by: Jean Delvare --- drivers/hwmon/amc6821.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c index 1c89d922d61..fa9708c2d72 100644 --- a/drivers/hwmon/amc6821.c +++ b/drivers/hwmon/amc6821.c @@ -686,7 +686,6 @@ static ssize_t set_fan1_div( data->fan1_div = 4; break; default: - mutex_unlock(&data->update_lock); count = -EINVAL; goto EXIT; } -- cgit v1.2.3-70-g09d2 From 5542482b9c61c2588f1178f315310a794988051a Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Mon, 25 Jan 2010 15:00:49 +0100 Subject: hwmon: (asus_atk0110) Do not fail if MBIF is missing MBIF (motherboard identification) is only used to print the name of the board, it's not essential for the driver; do not fail if it's missing. Based on Juan's patch. Signed-off-by: Luca Tettamanti Acked-by: Juan RP Signed-off-by: Jean Delvare --- drivers/hwmon/asus_atk0110.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 6811346c1c6..028284f544e 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -1329,17 +1329,16 @@ static int atk_add(struct acpi_device *device) &buf, ACPI_TYPE_PACKAGE); if (ret != AE_OK) { dev_dbg(&device->dev, "atk: method MBIF not found\n"); - err = -ENODEV; - goto out; - } - - obj = buf.pointer; - if (obj->package.count >= 2 && - obj->package.elements[1].type == ACPI_TYPE_STRING) { - dev_dbg(&device->dev, "board ID = %s\n", - obj->package.elements[1].string.pointer); + } else { + obj = buf.pointer; + if (obj->package.count >= 2) { + union acpi_object *id = &obj->package.elements[1]; + if (id->type == ACPI_TYPE_STRING) + dev_dbg(&device->dev, "board ID = %s\n", + id->string.pointer); + } + ACPI_FREE(buf.pointer); } - ACPI_FREE(buf.pointer); err = atk_probe_if(data); if (err) { -- cgit v1.2.3-70-g09d2 From c453615f77aa51593c1c9c9031b4278797d3fd19 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 25 Jan 2010 15:00:50 +0100 Subject: hwmon: (fschmd) Fix a memleak on multiple opens of /dev/watchdog When /dev/watchdog gets opened a second time we return -EBUSY, but we already have got a kref then, so we end up leaking our data struct. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare Cc: stable@kernel.org --- drivers/hwmon/fschmd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index bd0fc67e804..fa0728232e7 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c @@ -768,6 +768,7 @@ leave: static int watchdog_open(struct inode *inode, struct file *filp) { struct fschmd_data *pos, *data = NULL; + int watchdog_is_open; /* We get called from drivers/char/misc.c with misc_mtx hold, and we call misc_register() from fschmd_probe() with watchdog_data_mutex @@ -782,10 +783,12 @@ static int watchdog_open(struct inode *inode, struct file *filp) } } /* Note we can never not have found data, so we don't check for this */ - kref_get(&data->kref); + watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open); + if (!watchdog_is_open) + kref_get(&data->kref); mutex_unlock(&watchdog_data_mutex); - if (test_and_set_bit(0, &data->watchdog_is_open)) + if (watchdog_is_open) return -EBUSY; /* Start the watchdog */ -- cgit v1.2.3-70-g09d2 From ef39a1bf3c4fbdea085c618be424cc88b803f248 Mon Sep 17 00:00:00 2001 From: Denis Turischev Date: Thu, 21 Jan 2010 16:10:07 +0200 Subject: [WATCHDOG] sbc_fitpc2_wdt: fix I/O space access technique. The mdelay function was used between I/O access commands, that causes peak in CPU usage. Fix it by substitution mdelay to msleep. Expand usage on fitPC2 compatible boards according to DMI identification. Signed-off-by: Denis Turischev Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 4 ++-- drivers/watchdog/sbc_fitpc2_wdt.c | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 088f32f29a6..050ee147592 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -396,8 +396,8 @@ config SBC_FITPC2_WATCHDOG tristate "Compulab SBC-FITPC2 watchdog" depends on X86 ---help--- - This is the driver for the built-in watchdog timer on the fit-PC2 - Single-board computer made by Compulab. + This is the driver for the built-in watchdog timer on the fit-PC2, + fit-PC2i, CM-iAM single-board computers made by Compulab. It`s possible to enable watchdog timer either from BIOS (F2) or from booted Linux. When "Watchdog Timer Value" enabled one can set 31-255 s operational range. diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c index 91430a89107..e6763d2a567 100644 --- a/drivers/watchdog/sbc_fitpc2_wdt.c +++ b/drivers/watchdog/sbc_fitpc2_wdt.c @@ -46,9 +46,9 @@ static DEFINE_SPINLOCK(wdt_lock); static void wdt_send_data(unsigned char command, unsigned char data) { outb(command, COMMAND_PORT); - mdelay(100); + msleep(100); outb(data, DATA_PORT); - mdelay(200); + msleep(200); } static void wdt_enable(void) @@ -202,11 +202,10 @@ static int __init fitpc2_wdt_init(void) { int err; - if (strcmp("SBC-FITPC2", dmi_get_system_info(DMI_BOARD_NAME))) { - pr_info("board name is: %s. Should be SBC-FITPC2\n", - dmi_get_system_info(DMI_BOARD_NAME)); + if (!strstr(dmi_get_system_info(DMI_BOARD_NAME), "SBC-FITPC2")) return -ENODEV; - } + + pr_info("%s found\n", dmi_get_system_info(DMI_BOARD_NAME)); if (!request_region(COMMAND_PORT, 1, WATCHDOG_NAME)) { pr_err("I/O address 0x%04x already in use\n", COMMAND_PORT); -- cgit v1.2.3-70-g09d2 From 4f9a91c81273b66afe0b6a9be460b47581b28246 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Mon, 25 Jan 2010 15:46:58 -0800 Subject: qlge: Only free resources if they were allocated Currently qlge tries to release regions even if they were not allocated. This causes messages like the following in the kernel log Trying to free nonexistent resource <00000000006af400-00000000006af4ff> Trying to free nonexistent resource <00003c04ff9f4000-00003c04ff9f7fff> Trying to free nonexistent resource <00003c04ffc00000-00003c04ffcfffff> This patch fixes the goto logic in order to not release the resources if they were not allocated. Signed-off-by: Breno Leitao Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 707b391afa0..894a7c84fae 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -4119,7 +4119,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, err = pcie_set_readrq(pdev, 4096); if (err) { dev_err(&pdev->dev, "Set readrq failed.\n"); - goto err_out; + goto err_out1; } err = pci_request_regions(pdev, DRV_NAME); @@ -4140,7 +4140,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, if (err) { dev_err(&pdev->dev, "No usable DMA configuration.\n"); - goto err_out; + goto err_out2; } /* Set PCIe reset type for EEH to fundamental. */ @@ -4152,7 +4152,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, if (!qdev->reg_base) { dev_err(&pdev->dev, "Register mapping failed.\n"); err = -ENOMEM; - goto err_out; + goto err_out2; } qdev->doorbell_area_size = pci_resource_len(pdev, 3); @@ -4162,14 +4162,14 @@ static int __devinit ql_init_device(struct pci_dev *pdev, if (!qdev->doorbell_area) { dev_err(&pdev->dev, "Doorbell register mapping failed.\n"); err = -ENOMEM; - goto err_out; + goto err_out2; } err = ql_get_board_info(qdev); if (err) { dev_err(&pdev->dev, "Register access failed.\n"); err = -EIO; - goto err_out; + goto err_out2; } qdev->msg_enable = netif_msg_init(debug, default_msg); spin_lock_init(&qdev->hw_lock); @@ -4179,7 +4179,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, err = qdev->nic_ops->get_flash(qdev); if (err) { dev_err(&pdev->dev, "Invalid FLASH.\n"); - goto err_out; + goto err_out2; } memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); @@ -4212,8 +4212,9 @@ static int __devinit ql_init_device(struct pci_dev *pdev, DRV_NAME, DRV_VERSION); } return 0; -err_out: +err_out2: ql_release_all(pdev); +err_out1: pci_disable_device(pdev); return err; } -- cgit v1.2.3-70-g09d2 From 8704a2c8e9db24157a7b08d1678bf840f2318779 Mon Sep 17 00:00:00 2001 From: Guido Barzini Date: Mon, 25 Jan 2010 15:49:19 -0800 Subject: sfc: Add workspace for GMAC bug workaround to MCDI MAC_STATS buffer Due to a hardware bug in the SFC9000 family, the firmware must transfer raw GMAC statistics to host memory before aggregating them into the cooked (speed-independent) MAC statistics. Extend the stats buffer to support this. The length of the buffer is explicit in the MAC_STATS command, so this change is backward-compatible on both sides. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/mcdi_pcol.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sfc/mcdi_pcol.h b/drivers/net/sfc/mcdi_pcol.h index 2a85360a46f..73e71f42062 100644 --- a/drivers/net/sfc/mcdi_pcol.h +++ b/drivers/net/sfc/mcdi_pcol.h @@ -1090,8 +1090,10 @@ #define MC_CMD_MAC_RX_LANES01_DISP_ERR 57 #define MC_CMD_MAC_RX_LANES23_DISP_ERR 58 #define MC_CMD_MAC_RX_MATCH_FAULT 59 +#define MC_CMD_GMAC_DMABUF_START 64 +#define MC_CMD_GMAC_DMABUF_END 95 /* Insert new members here. */ -#define MC_CMD_MAC_GENERATION_END 60 +#define MC_CMD_MAC_GENERATION_END 96 #define MC_CMD_MAC_NSTATS (MC_CMD_MAC_GENERATION_END+1) /* MC_CMD_MAC_STATS: -- cgit v1.2.3-70-g09d2 From 5a27e86babe79cf5f575394bb1055448458df6c7 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 25 Jan 2010 15:49:59 -0800 Subject: sfc: Use fixed-size buffers for MCDI NVRAM requests The low-level MCDI code always uses 32-bit MMIO operations, and callers must pad input and output buffers to multiples of 4 bytes. The MCDI NVRAM functions are not doing this. Also, their buffers are declared as variable-length arrays with no explicit maximum length. Switch to a fixed buffer size based on the chunk size used by the MTD driver (which is a multiple of 4). Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/mcdi.c | 7 ++++--- drivers/net/sfc/mcdi.h | 1 + drivers/net/sfc/mtd.c | 5 ++--- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c index 0d4eba7266e..9f035b9f035 100644 --- a/drivers/net/sfc/mcdi.c +++ b/drivers/net/sfc/mcdi.c @@ -804,7 +804,7 @@ int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type, loff_t offset, u8 *buffer, size_t length) { u8 inbuf[MC_CMD_NVRAM_READ_IN_LEN]; - u8 outbuf[MC_CMD_NVRAM_READ_OUT_LEN(length)]; + u8 outbuf[MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX)]; size_t outlen; int rc; @@ -828,7 +828,7 @@ fail: int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type, loff_t offset, const u8 *buffer, size_t length) { - u8 inbuf[MC_CMD_NVRAM_WRITE_IN_LEN(length)]; + u8 inbuf[MC_CMD_NVRAM_WRITE_IN_LEN(EFX_MCDI_NVRAM_LEN_MAX)]; int rc; MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_TYPE, type); @@ -838,7 +838,8 @@ int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type, BUILD_BUG_ON(MC_CMD_NVRAM_WRITE_OUT_LEN != 0); - rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf, sizeof(inbuf), + rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf, + ALIGN(MC_CMD_NVRAM_WRITE_IN_LEN(length), 4), NULL, 0, NULL); if (rc) goto fail; diff --git a/drivers/net/sfc/mcdi.h b/drivers/net/sfc/mcdi.h index de916728c2e..10ce98f4c0f 100644 --- a/drivers/net/sfc/mcdi.h +++ b/drivers/net/sfc/mcdi.h @@ -111,6 +111,7 @@ extern int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type, extern int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type, loff_t offset, const u8 *buffer, size_t length); +#define EFX_MCDI_NVRAM_LEN_MAX 128 extern int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type, loff_t offset, size_t length); extern int efx_mcdi_nvram_update_finish(struct efx_nic *efx, diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c index 3a464529a46..407bbaddfea 100644 --- a/drivers/net/sfc/mtd.c +++ b/drivers/net/sfc/mtd.c @@ -23,7 +23,6 @@ #include "mcdi_pcol.h" #define EFX_SPI_VERIFY_BUF_LEN 16 -#define EFX_MCDI_CHUNK_LEN 128 struct efx_mtd_partition { struct mtd_info mtd; @@ -428,7 +427,7 @@ static int siena_mtd_read(struct mtd_info *mtd, loff_t start, int rc = 0; while (offset < end) { - chunk = min_t(size_t, end - offset, EFX_MCDI_CHUNK_LEN); + chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX); rc = efx_mcdi_nvram_read(efx, part->mcdi.nvram_type, offset, buffer, chunk); if (rc) @@ -491,7 +490,7 @@ static int siena_mtd_write(struct mtd_info *mtd, loff_t start, } while (offset < end) { - chunk = min_t(size_t, end - offset, EFX_MCDI_CHUNK_LEN); + chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX); rc = efx_mcdi_nvram_write(efx, part->mcdi.nvram_type, offset, buffer, chunk); if (rc) -- cgit v1.2.3-70-g09d2 From 39d321577405e8e269fd238b278aaf2425fa788a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 25 Jan 2010 15:51:01 -0800 Subject: virtio_net: Make delayed refill more reliable I have seen RX stalls on a machine that experienced a suspected OOM. After the stall, the RX buffer is empty on the guest side and there are exactly 16 entries available on the host side. As the number of entries is less than that required by a maximal skb, the host cannot proceed. The guest did not have a refill job scheduled. My diagnosis is that an OOM had occured, with the delayed refill job scheduled. The job was able to allocate at least one skb, but not enough to overcome the minimum required by the host to proceed. As the refill job would only reschedule itself if it failed completely to allocate any skbs, this would lead to an RX stall. The following patch removes this stall possibility by always rescheduling the refill job until the ring is totally refilled. Testing has shown that the RX stall no longer occurs whereas previously it would occur within a day. Signed-off-by: Herbert Xu Acked-by: Rusty Russell Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c708ecc3cb2..9ead30bd00c 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -395,8 +395,7 @@ static void refill_work(struct work_struct *work) vi = container_of(work, struct virtnet_info, refill.work); napi_disable(&vi->napi); - try_fill_recv(vi, GFP_KERNEL); - still_empty = (vi->num == 0); + still_empty = !try_fill_recv(vi, GFP_KERNEL); napi_enable(&vi->napi); /* In theory, this can happen: if we don't get any buffers in -- cgit v1.2.3-70-g09d2