brintos

brintos / linux-shallow public Read only

0
0
Text · 10.5 KiB · 1af69be Raw
405 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Abilis Systems Single DVB-T Receiver4 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>5 * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>6 */7 8#include <linux/kernel.h>9#include "as102_drv.h"10#include "as10x_cmd.h"11 12/**13 * as10x_cmd_turn_on - send turn on command to AS10x14 * @adap:   pointer to AS10x bus adapter15 *16 * Return 0 when no error, < 0 in case of error.17 */18int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap)19{20	int error = AS10X_CMD_ERROR;21	struct as10x_cmd_t *pcmd, *prsp;22 23	pcmd = adap->cmd;24	prsp = adap->rsp;25 26	/* prepare command */27	as10x_cmd_build(pcmd, (++adap->cmd_xid),28			sizeof(pcmd->body.turn_on.req));29 30	/* fill command */31	pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON);32 33	/* send command */34	if (adap->ops->xfer_cmd) {35		error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,36					    sizeof(pcmd->body.turn_on.req) +37					    HEADER_SIZE,38					    (uint8_t *) prsp,39					    sizeof(prsp->body.turn_on.rsp) +40					    HEADER_SIZE);41	}42 43	if (error < 0)44		goto out;45 46	/* parse response */47	error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNON_RSP);48 49out:50	return error;51}52 53/**54 * as10x_cmd_turn_off - send turn off command to AS10x55 * @adap:   pointer to AS10x bus adapter56 *57 * Return 0 on success or negative value in case of error.58 */59int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap)60{61	int error = AS10X_CMD_ERROR;62	struct as10x_cmd_t *pcmd, *prsp;63 64	pcmd = adap->cmd;65	prsp = adap->rsp;66 67	/* prepare command */68	as10x_cmd_build(pcmd, (++adap->cmd_xid),69			sizeof(pcmd->body.turn_off.req));70 71	/* fill command */72	pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF);73 74	/* send command */75	if (adap->ops->xfer_cmd) {76		error = adap->ops->xfer_cmd(77			adap, (uint8_t *) pcmd,78			sizeof(pcmd->body.turn_off.req) + HEADER_SIZE,79			(uint8_t *) prsp,80			sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE);81	}82 83	if (error < 0)84		goto out;85 86	/* parse response */87	error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNOFF_RSP);88 89out:90	return error;91}92 93/**94 * as10x_cmd_set_tune - send set tune command to AS10x95 * @adap:    pointer to AS10x bus adapter96 * @ptune:   tune parameters97 *98 * Return 0 on success or negative value in case of error.99 */100int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap,101		       struct as10x_tune_args *ptune)102{103	int error = AS10X_CMD_ERROR;104	struct as10x_cmd_t *preq, *prsp;105 106	preq = adap->cmd;107	prsp = adap->rsp;108 109	/* prepare command */110	as10x_cmd_build(preq, (++adap->cmd_xid),111			sizeof(preq->body.set_tune.req));112 113	/* fill command */114	preq->body.set_tune.req.proc_id = cpu_to_le16(CONTROL_PROC_SETTUNE);115	preq->body.set_tune.req.args.freq = (__force __u32)cpu_to_le32(ptune->freq);116	preq->body.set_tune.req.args.bandwidth = ptune->bandwidth;117	preq->body.set_tune.req.args.hier_select = ptune->hier_select;118	preq->body.set_tune.req.args.modulation = ptune->modulation;119	preq->body.set_tune.req.args.hierarchy = ptune->hierarchy;120	preq->body.set_tune.req.args.interleaving_mode  =121		ptune->interleaving_mode;122	preq->body.set_tune.req.args.code_rate  = ptune->code_rate;123	preq->body.set_tune.req.args.guard_interval = ptune->guard_interval;124	preq->body.set_tune.req.args.transmission_mode  =125		ptune->transmission_mode;126 127	/* send command */128	if (adap->ops->xfer_cmd) {129		error = adap->ops->xfer_cmd(adap,130					    (uint8_t *) preq,131					    sizeof(preq->body.set_tune.req)132					    + HEADER_SIZE,133					    (uint8_t *) prsp,134					    sizeof(prsp->body.set_tune.rsp)135					    + HEADER_SIZE);136	}137 138	if (error < 0)139		goto out;140 141	/* parse response */142	error = as10x_rsp_parse(prsp, CONTROL_PROC_SETTUNE_RSP);143 144out:145	return error;146}147 148/**149 * as10x_cmd_get_tune_status - send get tune status command to AS10x150 * @adap: pointer to AS10x bus adapter151 * @pstatus: pointer to updated status structure of the current tune152 *153 * Return 0 on success or negative value in case of error.154 */155int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap,156			      struct as10x_tune_status *pstatus)157{158	int error = AS10X_CMD_ERROR;159	struct as10x_cmd_t  *preq, *prsp;160 161	preq = adap->cmd;162	prsp = adap->rsp;163 164	/* prepare command */165	as10x_cmd_build(preq, (++adap->cmd_xid),166			sizeof(preq->body.get_tune_status.req));167 168	/* fill command */169	preq->body.get_tune_status.req.proc_id =170		cpu_to_le16(CONTROL_PROC_GETTUNESTAT);171 172	/* send command */173	if (adap->ops->xfer_cmd) {174		error = adap->ops->xfer_cmd(175			adap,176			(uint8_t *) preq,177			sizeof(preq->body.get_tune_status.req) + HEADER_SIZE,178			(uint8_t *) prsp,179			sizeof(prsp->body.get_tune_status.rsp) + HEADER_SIZE);180	}181 182	if (error < 0)183		goto out;184 185	/* parse response */186	error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTUNESTAT_RSP);187	if (error < 0)188		goto out;189 190	/* Response OK -> get response data */191	pstatus->tune_state = prsp->body.get_tune_status.rsp.sts.tune_state;192	pstatus->signal_strength  =193		le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.signal_strength);194	pstatus->PER = le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.PER);195	pstatus->BER = le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.BER);196 197out:198	return error;199}200 201/**202 * as10x_cmd_get_tps - send get TPS command to AS10x203 * @adap:      pointer to AS10x handle204 * @ptps:      pointer to TPS parameters structure205 *206 * Return 0 on success or negative value in case of error.207 */208int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps)209{210	int error = AS10X_CMD_ERROR;211	struct as10x_cmd_t *pcmd, *prsp;212 213	pcmd = adap->cmd;214	prsp = adap->rsp;215 216	/* prepare command */217	as10x_cmd_build(pcmd, (++adap->cmd_xid),218			sizeof(pcmd->body.get_tps.req));219 220	/* fill command */221	pcmd->body.get_tune_status.req.proc_id =222		cpu_to_le16(CONTROL_PROC_GETTPS);223 224	/* send command */225	if (adap->ops->xfer_cmd) {226		error = adap->ops->xfer_cmd(adap,227					    (uint8_t *) pcmd,228					    sizeof(pcmd->body.get_tps.req) +229					    HEADER_SIZE,230					    (uint8_t *) prsp,231					    sizeof(prsp->body.get_tps.rsp) +232					    HEADER_SIZE);233	}234 235	if (error < 0)236		goto out;237 238	/* parse response */239	error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTPS_RSP);240	if (error < 0)241		goto out;242 243	/* Response OK -> get response data */244	ptps->modulation = prsp->body.get_tps.rsp.tps.modulation;245	ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy;246	ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode;247	ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP;248	ptps->code_rate_LP = prsp->body.get_tps.rsp.tps.code_rate_LP;249	ptps->guard_interval = prsp->body.get_tps.rsp.tps.guard_interval;250	ptps->transmission_mode  = prsp->body.get_tps.rsp.tps.transmission_mode;251	ptps->DVBH_mask_HP = prsp->body.get_tps.rsp.tps.DVBH_mask_HP;252	ptps->DVBH_mask_LP = prsp->body.get_tps.rsp.tps.DVBH_mask_LP;253	ptps->cell_ID = le16_to_cpu((__force __le16)prsp->body.get_tps.rsp.tps.cell_ID);254 255out:256	return error;257}258 259/**260 * as10x_cmd_get_demod_stats - send get demod stats command to AS10x261 * @adap:          pointer to AS10x bus adapter262 * @pdemod_stats:  pointer to demod stats parameters structure263 *264 * Return 0 on success or negative value in case of error.265 */266int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap,267			      struct as10x_demod_stats *pdemod_stats)268{269	int error = AS10X_CMD_ERROR;270	struct as10x_cmd_t *pcmd, *prsp;271 272	pcmd = adap->cmd;273	prsp = adap->rsp;274 275	/* prepare command */276	as10x_cmd_build(pcmd, (++adap->cmd_xid),277			sizeof(pcmd->body.get_demod_stats.req));278 279	/* fill command */280	pcmd->body.get_demod_stats.req.proc_id =281		cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS);282 283	/* send command */284	if (adap->ops->xfer_cmd) {285		error = adap->ops->xfer_cmd(adap,286				(uint8_t *) pcmd,287				sizeof(pcmd->body.get_demod_stats.req)288				+ HEADER_SIZE,289				(uint8_t *) prsp,290				sizeof(prsp->body.get_demod_stats.rsp)291				+ HEADER_SIZE);292	}293 294	if (error < 0)295		goto out;296 297	/* parse response */298	error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_DEMOD_STATS_RSP);299	if (error < 0)300		goto out;301 302	/* Response OK -> get response data */303	pdemod_stats->frame_count =304		le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.frame_count);305	pdemod_stats->bad_frame_count =306		le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.bad_frame_count);307	pdemod_stats->bytes_fixed_by_rs =308		le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.bytes_fixed_by_rs);309	pdemod_stats->mer =310		le16_to_cpu((__force __le16)prsp->body.get_demod_stats.rsp.stats.mer);311	pdemod_stats->has_started =312		prsp->body.get_demod_stats.rsp.stats.has_started;313 314out:315	return error;316}317 318/**319 * as10x_cmd_get_impulse_resp - send get impulse response command to AS10x320 * @adap:     pointer to AS10x bus adapter321 * @is_ready: pointer to value indicating when impulse322 *	      response data is ready323 *324 * Return 0 on success or negative value in case of error.325 */326int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap,327			       uint8_t *is_ready)328{329	int error = AS10X_CMD_ERROR;330	struct as10x_cmd_t *pcmd, *prsp;331 332	pcmd = adap->cmd;333	prsp = adap->rsp;334 335	/* prepare command */336	as10x_cmd_build(pcmd, (++adap->cmd_xid),337			sizeof(pcmd->body.get_impulse_rsp.req));338 339	/* fill command */340	pcmd->body.get_impulse_rsp.req.proc_id =341		cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP);342 343	/* send command */344	if (adap->ops->xfer_cmd) {345		error = adap->ops->xfer_cmd(adap,346					(uint8_t *) pcmd,347					sizeof(pcmd->body.get_impulse_rsp.req)348					+ HEADER_SIZE,349					(uint8_t *) prsp,350					sizeof(prsp->body.get_impulse_rsp.rsp)351					+ HEADER_SIZE);352	}353 354	if (error < 0)355		goto out;356 357	/* parse response */358	error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_IMPULSE_RESP_RSP);359	if (error < 0)360		goto out;361 362	/* Response OK -> get response data */363	*is_ready = prsp->body.get_impulse_rsp.rsp.is_ready;364 365out:366	return error;367}368 369/**370 * as10x_cmd_build - build AS10x command header371 * @pcmd:     pointer to AS10x command buffer372 * @xid:      sequence id of the command373 * @cmd_len:  length of the command374 */375void as10x_cmd_build(struct as10x_cmd_t *pcmd,376		     uint16_t xid, uint16_t cmd_len)377{378	pcmd->header.req_id = cpu_to_le16(xid);379	pcmd->header.prog = cpu_to_le16(SERVICE_PROG_ID);380	pcmd->header.version = cpu_to_le16(SERVICE_PROG_VERSION);381	pcmd->header.data_len = cpu_to_le16(cmd_len);382}383 384/**385 * as10x_rsp_parse - Parse command response386 * @prsp:       pointer to AS10x command buffer387 * @proc_id:    id of the command388 *389 * Return 0 on success or negative value in case of error.390 */391int as10x_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)392{393	int error;394 395	/* extract command error code */396	error = prsp->body.common.rsp.error;397 398	if ((error == 0) &&399	    (le16_to_cpu(prsp->body.common.rsp.proc_id) == proc_id)) {400		return 0;401	}402 403	return AS10X_CMD_ERROR;404}405