/*
 * vivid-rds-gen.c - rds (radio data system) generator support functions.
 *
 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
 *
 * This program is free software; you may redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <linux/kernel.h>
#include <linux/ktime.h>
#include <linux/string.h>
#include <linux/videodev2.h>

#include "vivid-rds-gen.h"

static u8 vivid_get_di(const struct vivid_rds_gen *rds, unsigned grp)
{
	switch (grp) {
	case 0:
		return (rds->dyn_pty << 2) | (grp & 3);
	case 1:
		return (rds->compressed << 2) | (grp & 3);
	case 2:
		return (rds->art_head << 2) | (grp & 3);
	case 3:
		return (rds->mono_stereo << 2) | (grp & 3);
	}
	return 0;
}

/*
 * This RDS generator creates 57 RDS groups (one group == four RDS blocks).
 * Groups 0-3, 22-25 and 44-47 (spaced 22 groups apart) are filled with a
 * standard 0B group containing the PI code and PS name.
 *
 * Groups 4-19 and 26-41 use group 2A for the radio text.
 *
 * Group 56 contains the time (group 4A).
 *
 * All remaining groups use a filler group 15B block that just repeats
 * the PI and PTY codes.
 */
void vivid_rds_generate(struct vivid_rds_gen *rds)
{
	struct v4l2_rds_data *data = rds->data;
	unsigned grp;
	struct tm tm;
	unsigned date;
	unsigned time;
	int l;

	for (grp = 0; grp < VIVID_RDS_GEN_GROUPS; grp++, data += VIVID_RDS_GEN_BLKS_PER_GRP) {
		data[0].lsb = rds->picode & 0xff;
		data[0].msb = rds->picode >> 8;
		data[0].block = V4L2_RDS_BLOCK_A | (V4L2_RDS_BLOCK_A << 3);
		data[1].lsb = rds->pty << 5;
		data[1].msb = (rds->pty >> 3) | (rds->tp << 2);
		data[1].block = V4L2_RDS_BLOCK_B | (V4L2_RDS_BLOCK_B << 3);
		data[3].block = V4L2_RDS_BLOCK_D | (V4L2_RDS_BLOCK_D << 3);

		switch (grp) {
		case 0 ... 3:
		case 22 ... 25:
		case 44 ... 47: /* Group 0B */
			data[1].lsb |= (rds->ta << 4) | (rds->ms << 3);
			data[1].lsb |= vivid_get_di(rds, grp % 22);
			data[1].msb |= 1 << 3;
			data[2].lsb = rds->picode & 0xff;
			data[2].msb = rds->picode >> 8;
			data[2].block = V4L2_RDS_BLOCK_C_ALT | (V4L2_RDS_BLOCK_C_ALT << 3);
			data[3].lsb = rds->psname[2 * (grp % 22) + 1];
			data[3].msb = rds->psname[2 * (grp % 22)];
			break;
		case 4 ... 19:
		case 26 ... 41: /* Group 2A */
			data[1].lsb |= (grp - 4) % 22;
			data[1].msb |= 4 << 3;
			data[2].msb = rds->radiotext[4 * ((grp - 4) % 22)];
			data[2].lsb = rds->radiotext[4 * ((grp - 4) % 22) + 1];
			data[2].block = V4L2_RDS_BLOCK_C | (V4L2_RDS_BLOCK_C << 3);
			data[3].msb = rds->radiotext[4 * ((grp - 4) % 22) + 2];
			data[3].lsb = rds->radiotext[4 * ((grp - 4) % 22) + 3];
			break;
		case 56:
			/*
			 * Group 4A
			 *
			 * Uses the algorithm from Annex G of the RDS standard
			 * EN 50067:1998 to convert a UTC date to an RDS Modified
			 * Julian Day.
			 */
			time_to_tm(get_seconds(), 0, &tm);
			l = tm.tm_mon <= 1;
			date = 14956 + tm.tm_mday + ((tm.tm_year - l) * 1461) / 4 +
				((tm.tm_mon + 2 + l * 12) * 306001) / 10000;
			time = (tm.tm_hour << 12) |
			       (tm.tm_min << 6) |
			       (sys_tz.tz_minuteswest >= 0 ? 0x20 : 0) |
			       (abs(sys_tz.tz_minuteswest) / 30);
			data[1].lsb &= ~3;
			data[1].lsb |= date >> 15;
			data[1].msb |= 8 << 3;
			data[2].lsb = (date << 1) & 0xfe;
			data[2].lsb |= (time >> 16) & 1;
			data[2].msb = (date >> 7) & 0xff;
			data[2].block = V4L2_RDS_BLOCK_C | (V4L2_RDS_BLOCK_C << 3);
			data[3].lsb = time & 0xff;
			data[3].msb = (time >> 8) & 0xff;
			break;
		default: /* Group 15B */
			data[1].lsb |= (rds->ta << 4) | (rds->ms << 3);
			data[1].lsb |= vivid_get_di(rds, grp % 22);
			data[1].msb |= 0x1f << 3;
			data[2].lsb = rds->picode & 0xff;
			data[2].msb = rds->picode >> 8;
			data[2].block = V4L2_RDS_BLOCK_C_ALT | (V4L2_RDS_BLOCK_C_ALT << 3);
			data[3].lsb = rds->pty << 5;
			data[3].lsb |= (rds->ta << 4) | (rds->ms << 3);
			data[3].lsb |= vivid_get_di(rds, grp % 22);
			data[3].msb |= rds->pty >> 3;
			data[3].msb |= 0x1f << 3;
			break;
		}
	}
}

void vivid_rds_gen_fill(struct vivid_rds_gen *rds, unsigned freq,
			  bool alt)
{
	/* Alternate PTY between Info and Weather */
	if (rds->use_rbds) {
		rds->picode = 0x2e75; /* 'KLNX' call sign */
		rds->pty = alt ? 29 : 2;
	} else {
		rds->picode = 0x8088;
		rds->pty = alt ? 16 : 3;
	}
	rds->mono_stereo = true;
	rds->art_head = false;
	rds->compressed = false;
	rds->dyn_pty = false;
	rds->tp = true;
	rds->ta = alt;
	rds->ms = true;
	snprintf(rds->psname, sizeof(rds->psname), "%6d.%1d",
		 freq / 16, ((freq & 0xf) * 10) / 16);
	if (alt)
		strlcpy(rds->radiotext,
			" The Radio Data System can switch between different Radio Texts ",
			sizeof(rds->radiotext));
	else
		strlcpy(rds->radiotext,
			"An example of Radio Text as transmitted by the Radio Data System",
			sizeof(rds->radiotext));
}
